This code is Script 4c for Kitchel et al. “Biotic homogenization, the
exception and not the rule for marine fish communities” manuscript.
SESSION INFO TO DO
library(data.table)
library(vegan)
library(sf)
library(concaveman) #polygon around points
library(betapart) #allows us to partition beta diversity
library(geosphere)
library(ggpubr) #stat_regline_equation
library(nlme)
library(mgcv) #to make gam
library(cowplot)
library(lme4)
#Pull Dissimilarity Means
distances_dissimilarities_allyears.r <- readRDS(here::here("output","dissimilarities", "distances_dissimilarities_allyears.r.rds"))
#make survey and survey unit factors
distances_dissimilarities_allyears.r[,survey:=factor(survey)][,survey_unit:=factor(survey_unit)]
#adjust years
distances_dissimilarities_allyears.r[,year_adj := year-min(year)+1]
#add new variable for year in sequence per region
distances_dissimilarities_allyears.r[,first_year := min(year),.(survey_unit)]
distances_dissimilarities_allyears.r[,last_year := max(year),.(survey_unit)]
#distances_dissimilarities_allyears.r[,year_in_seq := year-first_year+1]
distances_dissimilarities_allyears.r[,years_sampled := last_year-first_year+1]
###Palette for Plotting Palette for plotting all 37 survey units
survey_unit.list <- levels(distances_dissimilarities_allyears.r[,survey_unit])
palette_42 <- c(
"#5A5156", #AI
"#DF00DB", #BITS-1
"#DB8EDA", #BITS-4
"#F6222E", #CHL
"#F8A19F", #DFO-NF
"#16FF32", #DFO-QCS
"#325A9B", #EBS
"#3283FE", #EVHOE
"#FEAF16", #FR-CGFS
"#fccb6d", #GMEX-Fall
"#1C8356", #GMEX-Summer
"#C4451C", #GOA
"#85660D", #GRL-DE
"#B0009F", #GSL-N
"#BF79B8", #GSL-S
"#1CBE4F", #ICE-GFS
"#782AB6", #IE-IGFS
"#90AD1C", #MEDITS
"#6B003A", #NAM
"#A75B00", #NEUS-Fall
"#E3B072", #NEUS-Spring
"#02E8B6", #NIGFS-1
"#97E7D5", #NIGFS-4
"#B00068", #Nor-BTS-3
"#00B9E3", #NS-IBTS-1
"#95E2F4", #NS-IBTS-3
"#B3CE73", #NZ-CHAT
"#689500", #NZ-ECSI
"#364d02",#NZ-SUBA
"#AAF400", #NZ-WCSI
"#AA0DFE", #PT-IBTS
"#7f9eb8", #ROCKALL
"#FA0087", #S-GEORG
"#DEA0FD", #SCS-Summer
"#FCEF88", #SEUS-fall
"#A59405", #SEUS-spring
"#FCE100", #SEUS-summer
"#544563", #SWC-IBTS-1
"#a37fc7", #SWC-IBTS-4
"#C075A6", #WCANN
"#BDCDFF", #ZAF-ATL
"#003EFF" #ZAF-IND
)
color_link <- data.table(survey_unit = survey_unit.list,hex = palette_42)
Add names for plotting
name_helper <- data.table(Survey_Name_Season = c("Aleutian Islands",
"Baltic Sea Q1",
"Baltic Sea Q4",
"Chile",
"Newfoundland",
"Queen Charlotte Sound",
"Eastern Bering Sea",
"Bay of Biscay",
"English Channel",
"Gulf of Mexico Summer",
"Gulf of Alaska",
"Greenland",
"N Gulf of St. Lawrence",
"S Gulf of St. Lawrence",
"Iceland",
"Irish Sea",
"Mediterranean",
"Namibia",
"NE US Fall",
"NE US Spring",
"N Ireland Q1",
"N Ireland Q4",
"Barents Sea Norway Q3",
"N Sea Q1",
"N Sea Q3",
"Chatham Rise NZ",
"E Coast S Island NZ",
"W Coast S Island NZ",
"Portugal",
"S Georgia",
"Scotian Shelf Summer",
"SE US Fall",
"SE US Spring",
"SE US Summer",
"W Coast US",
"Atlantic Ocean ZA",
"Indian Ocean ZA",
"Rockall Plateau",
"Scotland Shelf Sea Q1",
"Scotland Shelf Sea Q4",
"Falkland Islands",
"Gulf of Mexico Fall",
"Barents Sea Norway Q1",
"Sub-Arctic NZ",
"Scotian Shelf Spring"),
survey_unit = c(
"AI",
"BITS-1",
"BITS-4",
"CHL",
"DFO-NF",
"DFO-QCS",
"EBS",
"EVHOE",
"FR-CGFS",
"GMEX-Summer",
"GOA",
"GRL-DE",
"GSL-N",
"GSL-S",
"ICE-GFS",
"IE-IGFS",
"MEDITS",
"NAM",
"NEUS-Fall",
"NEUS-Spring",
"NIGFS-1",
"NIGFS-4",
"Nor-BTS-3",
"NS-IBTS-1",
"NS-IBTS-3",
"NZ-CHAT",
"NZ-ECSI",
"NZ-WCSI",
"PT-IBTS",
"S-GEORG",
"SCS-SUMMER",
"SEUS-fall",
"SEUS-spring",
"SEUS-summer",
"WCANN",
"ZAF-ATL",
"ZAF-IND",
"ROCKALL",
"SWC-IBTS-1",
"SWC-IBTS-4",
"FALK",
"GMEX-Fall",
"Nor-BTS-1",
"NZ-SUBA",
"SCS-SPRING"
))
color_link <- color_link[name_helper, on = "survey_unit"]
##Make GAMs
Bray Curtis
bray_curtis_gradient_gam <- gam(bray_curtis_dissimilarity_gradient_mean ~ year + s(survey_unit, year, bs = "fs", m = 1),#random smooth
data = distances_dissimilarities_allyears.r)
##Make LMERS
Bray These all converged
#running with lme instead of lmer gave same results, but allowed for calculation of p-value
bray_curtis_gradient_lme <- lme(bray_curtis_dissimilarity_gradient_mean ~ year_adj, random = (~1 + year_adj|survey_unit),data = distances_dissimilarities_allyears.r)
#but also run with lmer for confint
bray_curtis_gradient_lmer <- lmer(bray_curtis_dissimilarity_gradient_mean ~ year_adj + (1 + year_adj|survey_unit),data = distances_dissimilarities_allyears.r)
Warning: Model failed to converge with max|grad| = 0.012616 (tol = 0.002, component 1)
summary(bray_curtis_gradient_lme)
Linear mixed-effects model fit by REML
Data: distances_dissimilarities_allyears.r
Random effects:
Formula: ~1 + year_adj | survey_unit
Structure: General positive-definite, Log-Cholesky parametrization
StdDev Corr
(Intercept) 0.087744906 (Intr)
year_adj 0.001126915 -0.8
Residual 0.022459795
Fixed effects: bray_curtis_dissimilarity_gradient_mean ~ year_adj
Correlation:
(Intr)
year_adj -0.812
Standardized Within-Group Residuals:
Min Q1 Med Q3 Max
-3.50705109 -0.58169508 -0.02326812 0.50523697 5.05664006
Number of Observations: 897
Number of Groups: 42
anova(bray_curtis_gradient_lme)
bray_curtis_gradient_coefs <- data.table(coef(bray_curtis_gradient_lme))
bray_curtis_gradient_coefs[,survey_unit := rownames(coef(bray_curtis_gradient_lme))][,Year := round(year_adj,5)][,Intercept := round(`(Intercept)`,2)]
View(bray_curtis_gradient_coefs)
bray_curtis_gradient_coefs <- bray_curtis_gradient_coefs[color_link, on = "survey_unit"]
bray_curtis_gradient_coefs.exp <- bray_curtis_gradient_coefs[,.(Survey_Name_Season, Intercept, Year)]
#export this table
fwrite(bray_curtis_gradient_coefs.exp, file = here::here("output","bray_curtis_gradient_coefs.exp.csv"))
Get LMER model as predictions
# need to sort out year in seq versus overall year models
#new data for lmer
lmer_year <- seq(min(distances_dissimilarities_allyears.r[,year]), max(distances_dissimilarities_allyears.r[,year]), by = 0.1)
lmer_year_adj <- seq(min(distances_dissimilarities_allyears.r[,year_adj]), max(distances_dissimilarities_allyears.r[,year_adj]), by = 0.1)
#predict average lmer
lmer_bray_gradient_predictions <- data.table(year = lmer_year, year_adj = lmer_year_adj)
#confidence intervals
bray_curtis_gradient_lmer_confint <- confint(bray_curtis_gradient_lmer)
Computing profile confidence intervals ...
#populate data table of lmer predictions
lmer_bray_gradient_predictions[,bray_curtis_lmer_preds := fixef(bray_curtis_gradient_lmer)[[1]] + fixef(bray_curtis_gradient_lmer)[[2]] * year_adj][,bray_curtis_lmer_preds_lowerCI := bray_curtis_gradient_lmer_confint[5] + bray_curtis_gradient_lmer_confint[6] * year_adj][,bray_curtis_lmer_preds_upperCI := bray_curtis_gradient_lmer_confint[11] + bray_curtis_gradient_lmer_confint[12] * year_adj]
###Move forward with Bray Curtis Gradient (others to supplement)
Coefficients for LMER by survey_unit
#unique survey unit year combos
survey_unit_sampling_years <- unique(distances_dissimilarities_allyears.r[,.(survey_unit, year_adj, year, years_sampled)])
# see group coefficients
model_coefs_reduced <- data.table(transform(as.data.frame(ranef(bray_curtis_gradient_lmer)), lwr = condval - 1.96*condsd, upr = condval + 1.96*condsd))
#https://stackoverflow.com/questions/69805532/extract-the-confidence-intervals-of-lmer-random-effects-plotted-with-dotplotra
#ONLY SLOPES
model_coefs_reduced <- model_coefs_reduced[term == "year_adj",]
model_coefs_reduced[,survey_unit := grp][,year_adj := condval]
#merge with duration of survey
model_coefs_reduced_length <- model_coefs_reduced[survey_unit_sampling_years, on = "survey_unit"]
model_coefs_reduced_length[,years_sampled := as.numeric(years_sampled)][,Directional_Change := ifelse(year_adj > 0, "Differentiation","Homogenization")]
#does it cross zero?
model_coefs_reduced_length[,significant := ifelse(lwr >0 & upr>0,T,ifelse(lwr<0 & upr<0,T,F))]
#significant directional change
model_coefs_reduced_length[,Directional_Change_sig := ifelse(year_adj > 0 & significant == T, "Differentiation",ifelse(year_adj < 0 & significant == T, "Homogenization", "No trend in\ndissimilarity"))]
#min max distances_dissimilarities
min_bray_reduced <- min(distances_dissimilarities_allyears.r[,bray_curtis_dissimilarity_gradient_mean], na.rm = T)
max_bray_reduced <- max(distances_dissimilarities_allyears.r[,bray_curtis_dissimilarity_gradient_mean], na.rm = T)
model_coefs_reduced_length <- model_coefs_reduced_length[color_link, on = "survey_unit"]
#delete any NAs
model_coefs_reduced_length <- na.omit(model_coefs_reduced_length, cols = "significant")
#order table by coefficient
setorder(model_coefs_reduced_length, year_adj)
BC_gradient_model_coefs_reduced_length.unique <- unique(model_coefs_reduced_length[,.(condval,condsd, lwr, upr, survey_unit, year_adj, years_sampled, Directional_Change, hex, Survey_Name_Season, significant, Directional_Change_sig)])
#extract color hexes
#year adj coef order
color_year_adj_order <- BC_gradient_model_coefs_reduced_length.unique[,hex]
#alphabetical order
BC_gradient_model_coefs_reduced_length.unique.alpha <- setorder(BC_gradient_model_coefs_reduced_length.unique, Survey_Name_Season)
BC_gradient_model_coefs_reduced_length.unique.alpha[,trend_color := ifelse(Directional_Change_sig == "Homogenization", "#e7ac5b", ifelse(Directional_Change_sig == "Differentiation","#91c874","#cbbfde"))]
color_alpha_order <- BC_gradient_model_coefs_reduced_length.unique.alpha[,hex]
color_alpha_order_bytrend <- BC_gradient_model_coefs_reduced_length.unique.alpha[, trend_color]
saveRDS(BC_gradient_model_coefs_reduced_length.unique, here::here("output","region_stats","BC_gradient_model_coefs_reduced_length.unique.Rds"))
Bar Plot Coefficient LMER
BC_GRADIENT_Dissimilarity_Coef_errorbar_reduced <- ggplot() +
geom_errorbar(data = model_coefs_reduced_length, aes(x = reorder(Survey_Name_Season, year_adj) , y = year_adj, label = Survey_Name_Season, ymin = lwr, ymax = upr), fill = "grey", width = 0) + #add confidence intervals
geom_point(data = model_coefs_reduced_length, aes(x = reorder(Survey_Name_Season, year_adj) , y = year_adj, label = Survey_Name_Season, size = years_sampled, fill = Directional_Change_sig, color = Directional_Change_sig), stat = 'identity', shape = 21) +
scale_fill_manual(values = c("white","black","grey"), name = "Dissimilarity trend", guide="none") +
scale_color_manual(values = c("black","black","grey"), name = "Dissimilarity trend", guide="none") +
scale_size_binned(range = c(1,8), name = "Survey period length") +
geom_hline(yintercept = 0) +
scale_y_continuous(breaks = seq(-0.005, 0.0075, by = 0.0025), labels = c("-0.005","","0", "", "0.005", "")) +
xlab("Survey unit") +
ylab("β-diversity trend") + #gradient BC dissimilarity trend
coord_flip() +
theme_classic() +
theme(axis.text.y = element_text(colour = color_year_adj_order, face = "bold"), axis.title.y = element_blank(), axis.text.x = element_text(size = 15), axis.title.x = element_text(size = 15), legend.position = c(0.2,0.8), legend.direction = "vertical", legend.background = element_rect(fill = "transparent"))
Warning: Ignoring unknown parameters: `fill`Warning: Ignoring unknown aesthetics: labelWarning: Ignoring unknown aesthetics: labelWarning: Vectorized input to `element_text()` is not officially supported.
ℹ Results may be unexpected or may change in future versions of ggplot2.
#pull legend for homogenization
directional_change_legend_plot <- BC_GRADIENT_Dissimilarity_Coef_errorbar_reduced +
scale_fill_manual(values = c("white","black","grey"), name = "Dissimilarity trend") +
scale_color_manual(values = c("black","black","grey"), name = "Dissimilarity trend") +
scale_size_binned(range = c(1,8), name = "Survey period length", guide = "none") +
theme(legend.position = "right", legend.background = element_rect(fill= "transparent")) +
guides(colour = guide_legend(override.aes = list(size=6)))
Scale for fill is already present.
Adding another scale for fill, which will replace the existing scale.Scale for colour is already present.
Adding another scale for colour, which will replace the existing scale.Scale for size is already present.
Adding another scale for size, which will replace the existing scale.
BC_GRADIENT_Dissimilarity_Coef_errorbar_reduced

#ALT grey scale
BC_GRADIENT_Dissimilarity_Coef_errorbar_reduced_greyscale <- ggplot() +
geom_errorbar(data = model_coefs_reduced_length, aes(x = reorder(Survey_Name_Season, year_adj) , y = year_adj, label = Survey_Name_Season, ymin = lwr, ymax = upr), fill = "grey", width = 0) + #add confidence intervals
geom_point(data = model_coefs_reduced_length, aes(x = reorder(Survey_Name_Season, year_adj) , y = year_adj, label = Survey_Name_Season, size = years_sampled, fill = Directional_Change_sig, color = Directional_Change_sig), stat = 'identity', shape = 21) +
scale_fill_manual(values = c("white","black","grey"), name = "Dissimilarity trend", guide="none") +
scale_color_manual(values = c("black","black","grey"), name = "Dissimilarity trend", guide="none") +
scale_size_binned(range = c(1,8), name = "Survey period length") +
geom_hline(yintercept = 0) +
scale_y_continuous(breaks = seq(-0.005, 0.0075, by = 0.0025), labels = c("-0.005","","0", "", "0.005", "")) +
xlab("Survey unit") +
ylab("β-diversity trend") + #gradient BC dissimilarity trend
coord_flip() +
theme_classic() +
theme(axis.text.y = element_text(face = "bold"), axis.title.y = element_blank(), axis.text.x = element_text(size = 15), axis.title.x = element_text(size = 15), legend.position = c(0.25,0.8), legend.direction = "vertical")
Warning: Ignoring unknown parameters: `fill`Warning: Ignoring unknown aesthetics: labelWarning: Ignoring unknown aesthetics: label
Alternatively, we color this plot by trend experienced
BC_gradient_Dissimilarity_Coef_errorbar_reduced_colorbytrend <- ggplot() +
geom_errorbar(data = model_coefs_reduced_length, aes(x = reorder(Survey_Name_Season, year_adj) , y = year_adj, label = Survey_Name_Season, ymin = lwr, ymax = upr), fill = "grey", width = 0) + #add confidence intervals
geom_point(data = model_coefs_reduced_length, aes(x = reorder(Survey_Name_Season, year_adj) , y = year_adj, label = Survey_Name_Season, size = years_sampled, color = Directional_Change_sig), stat = 'identity') +
scale_color_manual(values = c("#73BA4D","#E0962C","#cbbfde"), name = "Dissimilarity trend", guide="none") +
scale_size_binned(range = c(1,8), name = "Survey period length\n(years)") +
geom_hline(yintercept = 0) +
# scale_y_continuous(breaks = seq(-0.005, 0.0075, by = 0.0025), labels = c("-0.005","","0", "", "0.005", "")) +
xlab("Survey unit") +
ylab("β-diversity trend") + #gradient BC dissimilarity trend
coord_flip() +
theme_classic() +
theme(axis.text.y = element_text(face = "bold"), axis.title.y = element_blank(), axis.text.x = element_text(size = 15), axis.title.x = element_text(size = 15), legend.position = c(0.25,0.8), legend.direction = "vertical", legend.text = element_text(size = 14), legend.title = element_text(size = 15), legend.background = element_rect(fill = "transparent"))
Warning: Ignoring unknown parameters: `fill`Warning: Ignoring unknown aesthetics: labelWarning: Ignoring unknown aesthetics: label
Wavy Line Plot for GAMs
Generate predicted values
#add colors and names to full dissimilarity data table
distances_dissimilarities_allyears.r <- distances_dissimilarities_allyears.r[color_link, on = "survey_unit"]
#generate new data to smooth lines (need year and season survey combinations)
year_survey_unit_expand.dt <- data.table(survey_unit = as.character(NULL), year = as.numeric(NULL), year_adj = as.numeric(NULL ))
for (i in 1:length(survey_unit.list)) {
#generate year vectors
survey_unit_years <- unique(distances_dissimilarities_allyears.r[survey_unit == survey_unit.list[i],.(survey_unit, year, year_adj)])
years <- seq(min(survey_unit_years[,year]), max(survey_unit_years[,year]), by = 0.1)
year_adjust <- seq(min(survey_unit_years[,year_adj]), max(survey_unit_years[,year_adj]), by = 0.1)
year_survey_unit_expand.dt_addition <- data.table(survey_unit = survey_unit.list[i], year = years, year_adj = year_adjust)
year_survey_unit_expand.dt <- rbind(year_survey_unit_expand.dt, year_survey_unit_expand.dt_addition)
}
#add colors and names to full year and survey unit combination table
year_survey_unit_expand.dt <- year_survey_unit_expand.dt[color_link, on = "survey_unit"]
Get model as predictions
#for plotting, get model as predictions
bray_curtis_gradient_gam_predictions <- predict(bray_curtis_gradient_gam, se.fit = TRUE, newdata = year_survey_unit_expand.dt)
#merge into table
year_survey_unit_expand.dt[,bray_glm_mod_fit := bray_curtis_gradient_gam_predictions$fit][,bray_glm_mod_fit_SE := bray_curtis_gradient_gam_predictions$se.fit]
Produce Plot of GAM and mean LMER line
points_wavylines_bray_gradient_year_reduced_gam_nolmer <- ggplot() +
# geom_ribbon(data = lmer_bray_gradient_predictions, aes(x = year, ymin = bray_curtis_lmer_preds_lowerCI, ymax = bray_curtis_lmer_preds_upperCI), fill = "grey", alpha = 0.2) +
geom_point(data = na.omit(distances_dissimilarities_allyears.r,cols = "year_adj"),
aes(x = year,
y = bray_curtis_dissimilarity_gradient_mean,
color = Survey_Name_Season), alpha = 0.5, size = 1) +
geom_line(data = na.omit(year_survey_unit_expand.dt,cols = "year_adj"),
aes(x = year,
y = bray_glm_mod_fit,
color = Survey_Name_Season)) +
geom_ribbon(data = na.omit(year_survey_unit_expand.dt,cols = "year_adj"), aes(x = year, ymin=bray_glm_mod_fit-bray_glm_mod_fit_SE, ymax=bray_glm_mod_fit+bray_glm_mod_fit_SE, fill = Survey_Name_Season), alpha=0.1) + #add standard error
# geom_line(data = lmer_bray_gradient_predictions, aes(x = year, y = bray_curtis_lmer_preds), color = "black") +
scale_color_manual(values = color_alpha_order, name = "Survey Unit") +
scale_fill_manual(values = color_alpha_order, guide = "none") +
theme_classic() +
lims(x = c(min(distances_dissimilarities_allyears.r[,year]),max(distances_dissimilarities_allyears.r[,year])),
y = c(0,0.5)) +
xlab("Year") +
ylab("Gradient BC dissimilarity") +
theme(legend.position = "null")
points_wavylines_bray_gradient_year_reduced_gam_nolmer
ggsave(points_wavylines_bray_gradient_year_reduced_gam_nolmer, path = here::here("figures"), filename ="points_wavylines_bray_gradient_year_reduced_gam_nolmer.jpg", height = 5, width = 5, unit = "in")

#with lmer
points_wavylines_bray_gradient_year_reduced_gam <- ggplot() +
geom_ribbon(data = lmer_bray_gradient_predictions, aes(x = year, ymin = bray_curtis_lmer_preds_lowerCI, ymax = bray_curtis_lmer_preds_upperCI), fill = "grey", alpha = 0.3) +
geom_point(data = na.omit(distances_dissimilarities_allyears.r, cols = "year_adj"),
aes(x = year,
y = bray_curtis_dissimilarity_gradient_mean,
fill = Survey_Name_Season), alpha = 0.4, size = 1, shape = 21, color = "white") +
geom_line(data = na.omit(year_survey_unit_expand.dt, cols = "year_adj"),
aes(x = year,
y = bray_glm_mod_fit,
color = Survey_Name_Season), alpha = 0.6) +
geom_ribbon(data = na.omit(year_survey_unit_expand.dt, cols = "year_adj"), aes(x = year, ymin=bray_glm_mod_fit-bray_glm_mod_fit_SE, ymax=bray_glm_mod_fit+bray_glm_mod_fit_SE, fill = Survey_Name_Season), alpha=0.1) + #add standard error
geom_line(data = lmer_bray_gradient_predictions, aes(x = year, y = bray_curtis_lmer_preds), color = "black") +
scale_color_manual(values = color_alpha_order, name = "Survey Unit") +
scale_fill_manual(values = color_alpha_order, guide = "none") +
theme_classic() +
lims(x = c(min(distances_dissimilarities_allyears.r[,year]),max(distances_dissimilarities_allyears.r[,year])),
y = c(0,0.5)) +
xlab("Year") +
ylab("β-diversity") +
theme(legend.position = "null", axis.text = element_text(size = 15), axis.title = element_text(size = 15))
points_wavylines_bray_gradient_year_reduced_gam
ggsave(points_wavylines_bray_gradient_year_reduced_gam, path = here::here("figures"), filename ="points_wavylines_bray_gradient_year_reduced_gam.jpg", height = 6, width = 6, unit = "in")

#ALT
#plot all, but same color scheme (grey)
points_wavylines_bray_gradient_year_reduced_gam_greyscale <- ggplot() +
geom_ribbon(data = lmer_bray_gradient_predictions, aes(x = year, ymin = bray_curtis_lmer_preds_lowerCI, ymax = bray_curtis_lmer_preds_upperCI), fill = "grey", alpha = 0.3) +
geom_point(data = distances_dissimilarities_allyears.r,
aes(x = year,
y = bray_curtis_dissimilarity_gradient_mean,
fill = Survey_Name_Season), alpha = 0.4, size = 1, shape = 21, color = "white") +
geom_line(data = year_survey_unit_expand.dt,
aes(x = year,
y = bray_glm_mod_fit,
color = Survey_Name_Season), alpha = 0.6) +
geom_ribbon(data = year_survey_unit_expand.dt, aes(x = year, ymin=bray_glm_mod_fit-bray_glm_mod_fit_SE, ymax=bray_glm_mod_fit+bray_glm_mod_fit_SE, fill = Survey_Name_Season), alpha=0.1) + #add standard error
geom_line(data = lmer_bray_gradient_predictions, aes(x = year, y = bray_curtis_lmer_preds), color = "black") +
scale_color_manual(values = rep("black", times = length(unique(distances_dissimilarities_allyears.r$Survey_Name_Season))), name = "Survey Unit") +
scale_fill_manual(values = rep("black", times = length(unique(distances_dissimilarities_allyears.r$Survey_Name_Season))), guide = "none") +
theme_classic() +
lims(x = c(min(distances_dissimilarities_allyears.r[,year]),max(distances_dissimilarities_allyears.r[,year])),
y = c(0,0.5)) +
xlab("Year") +
ylab("β-diversity") +
theme(legend.position = "null", axis.text = element_text(size = 15), axis.title = element_text(size = 15))
points_wavylines_bray_gradient_year_reduced_gam_greyscale
ggsave(points_wavylines_bray_gradient_year_reduced_gam_greyscale, path = here::here("figures"), filename ="points_wavylines_bray_gradient_year_reduced_gam_greyscale.jpg", height = 6, width = 6, unit = "in")

Alternative, color by trend
points_wavylines_bray_gradient_year_reduced_gam_colorbytrend <- ggplot() +
geom_ribbon(data = lmer_bray_gradient_predictions, aes(x = year, ymin = bray_curtis_lmer_preds_lowerCI, ymax = bray_curtis_lmer_preds_upperCI), fill = "grey", alpha = 0.3) +
geom_point(data = na.omit(distances_dissimilarities_allyears.r, cols = "year_adj"),
aes(x = year,
y = bray_curtis_dissimilarity_gradient_mean,
fill = Survey_Name_Season), alpha = 0.4, size = 1, shape = 21, color = "white") +
geom_line(data = na.omit(year_survey_unit_expand.dt, cols = "year_adj"),
aes(x = year,
y = bray_glm_mod_fit,
color = Survey_Name_Season), alpha = 0.6) +
geom_ribbon(data = na.omit(year_survey_unit_expand.dt, cols = "year_adj"), aes(x = year, ymin=bray_glm_mod_fit-bray_glm_mod_fit_SE, ymax=bray_glm_mod_fit+bray_glm_mod_fit_SE, fill = Survey_Name_Season), alpha=0.1) + #add standard error
geom_line(data = lmer_bray_gradient_predictions, aes(x = year, y = bray_curtis_lmer_preds), color = "black") +
scale_color_manual(values = color_alpha_order_bytrend, name = "Survey Unit") +
scale_fill_manual(values = color_alpha_order_bytrend, guide = "none") +
theme_classic() +
lims(x = c(min(distances_dissimilarities_allyears.r[,year]),max(distances_dissimilarities_allyears.r[,year]))) +
xlab("Year") +
ylab("β-diversity") +
theme(legend.position = "null", axis.text = element_text(size = 15), axis.title = element_text(size = 15))
points_wavylines_bray_gradient_year_reduced_gam_colorbytrend
ggsave(points_wavylines_bray_gradient_year_reduced_gam_colorbytrend, path = here::here("figures"), filename ="points_wavylines_bray_gradient_year_reduced_gam_colorbytrend.jpg", height = 6, width = 6, unit = "in")

#plot each independently for supplement
#all survey names =
all_survey_names <- sort(unique(distances_dissimilarities_allyears.r$Survey_Name_Season))
#list of plots
points_wavylines_bray_gradient_year_reduced_gam_individual <- list()
for (i in 1:length(all_survey_names)) {
points_wavylines_bray_gradient_year_reduced_gam_individual[[i]] <- ggplot() +
geom_point(data = distances_dissimilarities_allyears.r[Survey_Name_Season == all_survey_names[i]],
aes(x = year,
y = bray_curtis_dissimilarity_gradient_mean), alpha = 0.4, color = "black") +
geom_line(data = year_survey_unit_expand.dt[Survey_Name_Season == all_survey_names[i]],
aes(x = year,
y = bray_glm_mod_fit), alpha = 0.6) +
geom_ribbon(data = year_survey_unit_expand.dt[Survey_Name_Season == all_survey_names[i]], aes(x = year, ymin=bray_glm_mod_fit-bray_glm_mod_fit_SE, ymax=bray_glm_mod_fit+bray_glm_mod_fit_SE), alpha=0.1) + #add standard error
theme_classic() +
# lims(x = c(min(distances_dissimilarities_allyears.r[Survey_Name_Season == all_survey_names[i],year]),max(distances_dissimilarities_allyears.r[Survey_Name_Season == all_survey_names[i],year])),
# y = c(0,0.5)) +
xlab("Year") +
ylab("beta-diversity") +
facet_wrap(~Survey_Name_Season, ncol = 5) +
theme(legend.position = "null", axis.text = element_text(size = 15), axis.title = element_text(size = 15))
print(points_wavylines_bray_gradient_year_reduced_gam_individual[[i]])
}












































saveRDS(points_wavylines_bray_gradient_year_reduced_gam_individual, here::here("figures","points_wavylines_bray_gradient_year_reduced_gam_individual.Rds"))
#print to pdf
library(gridExtra)
ggsave(
filename = here::here("figures","points_wavylines_bray_gradient_year_reduced_gam_individual.pdf"),
plot = marrangeGrob(points_wavylines_bray_gradient_year_reduced_gam_individual, nrow=1, ncol=1),
width = 8.5, height = 11
)
Warning: Removed 1 rows containing missing values (`geom_point()`).Warning: Removed 1 row containing missing values (`geom_line()`).Warning: no non-missing arguments to max; returning -InfWarning: Removed 1 rows containing missing values (`geom_point()`).Warning: Removed 1 row containing missing values (`geom_line()`).Warning: no non-missing arguments to max; returning -InfWarning: Removed 1 rows containing missing values (`geom_point()`).Warning: Removed 1 row containing missing values (`geom_line()`).Warning: no non-missing arguments to max; returning -Inf

Merge BC versus Year plot with GAMS and Region vs. coefficient plot
for LMERs
BC_GRADIENT_GAM_LMER_merge_legend <- ggdraw(xlim = c(0, 40.5), ylim = c(0, 21)) +
draw_plot(points_wavylines_bray_gradient_year_reduced_gam,
x = 1, y = 1, width = 20, height = 20) +
draw_plot(BC_GRADIENT_Dissimilarity_Coef_errorbar_reduced +
theme(legend.key.size = unit(0.5, 'cm'), #change legend key size
legend.title = element_text(size=16), #change legend title font size
legend.text = element_text(size=14)), #change legend text font size),
x = 20, y = 1, width =19, height = 20) +
draw_plot(get_legend(directional_change_legend_plot +
theme(legend.key.size = unit(0.5, 'cm'), #change legend key size
legend.title = element_text(size=15), #change legend title font size
legend.text = element_text(size=13))), #change legend text font size)
x = 27, y = 12, width = 3, height = 2) +
geom_text(aes(x = 2, y = 20.7), label = ("a."), size =8, fontface = "bold") +
geom_text(aes(x =20, y = 20.7), label = ("b."), size =8, fontface = "bold")
ggsave(BC_GRADIENT_GAM_LMER_merge_legend, path = here::here("figures"), filename = "BC_GRADIENT_GAM_LMER_merge_legend.png", height = 8, width = 14, units = "in")
#ALT GREY SCALE
BC_GRADIENT_GAM_LMER_merge_legend_greyscale <- ggdraw(xlim = c(0, 40.5), ylim = c(0, 21)) +
draw_plot(points_wavylines_bray_gradient_year_reduced_gam_greyscale,
x = 1, y = 1, width = 20, height = 20) +
draw_plot(BC_GRADIENT_Dissimilarity_Coef_errorbar_reduced_greyscale +
theme(legend.key.size = unit(0.5, 'cm'), #change legend key size
legend.title = element_text(size=16), #change legend title font size
legend.text = element_text(size=14)), #change legend text font size),
x = 20, y = 1, width = 19, height = 20) +
draw_plot(get_legend(directional_change_legend_plot +
theme(legend.key.size = unit(0.5, 'cm'), #change legend key size
legend.title = element_text(size=15), #change legend title font size
legend.text = element_text(size=13))), #change legend text font size)
x = 27, y = 12, width = 3, height = 2) +
geom_text(aes(x = 2, y = 20.7), label = ("a."), size =8, fontface = "bold") +
geom_text(aes(x =20, y = 20.7), label = ("b."), size =8, fontface = "bold")
ggsave(BC_GRADIENT_GAM_LMER_merge_legend_greyscale, path = here::here("figures"), filename = "BC_GRADIENT_GAM_LMER_merge_legend_greyscale.png", height = 8, width = 14, units = "in")
#ALT COLOR BY TREND
BC_gradient_GAM_LMER_merge_legend_colorbytrend <- ggdraw(xlim = c(0, 40.5), ylim = c(0, 21)) +
draw_plot(points_wavylines_bray_gradient_year_reduced_gam_colorbytrend,
x = 1, y = 1, width = 20, height = 20) +
draw_plot(BC_gradient_Dissimilarity_Coef_errorbar_reduced_colorbytrend +
theme(legend.key.size = unit(0.5, 'cm'), #change legend key size
# legend.title = element_text(size=16), #change legend title font size
# legend.text = element_text(size=14)
), #change legend text font size),
x = 20, y = 1, width = 19, height = 20) +
draw_plot(get_legend(directional_change_legend_plot_colorbytrend +
theme(legend.key.size = unit(0.5, 'cm'), #change legend key size
legend.title = element_text(size=16), #change legend title font size
legend.text = element_text(size=15))), #change legend text font size)
x = 30, y = 6, width = 3, height = 2) +
geom_text(aes(x = 2, y = 20.7), label = ("a."), size =8, fontface = "bold") +
geom_text(aes(x =20, y = 20.7), label = ("b."), size =8, fontface = "bold")
ggsave(BC_gradient_GAM_LMER_merge_legend_colorbytrend, path = here::here("figures"), filename = "BC_gradient_GAM_LMER_merge_legend_colorbytrend.png", height = 8, width = 14, units = "in")
LS0tCnRpdGxlOiAiWWVhciBHcmFkaWVudCBEaXNzaW1pbGFyaXR5IE1vZGVscyAobmVzdGVkbmVzcykiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KClRoaXMgY29kZSBpcyBTY3JpcHQgNGMgZm9yIEtpdGNoZWwgZXQgYWwuICJCaW90aWMgaG9tb2dlbml6YXRpb24sIHRoZSBleGNlcHRpb24gYW5kIG5vdCB0aGUgcnVsZSBmb3IgbWFyaW5lIGZpc2ggY29tbXVuaXRpZXMiIG1hbnVzY3JpcHQuCgotIFRoaXMgcHJvamVjdCBpcyBhIGNvbGxhYm9yYXRpdmUgZWZmb3J0IHRvIGRlc2NyaWJlIGNoYW5nZXMgaW4gdGF4b25vbWljIGNvbXBvc2l0aW9uICBvZiBmaXNoIGNvbW11bml0aWVzIGFyb3VuZCB0aGUgd29ybGQtLWFzIHNhbXBsZWQgYnkgYm90dG9tIHRyYXdsIHN1cnZleXMuCgotIENvZGUgYnkgWm/DqyBKLiBLaXRjaGVsCgpTRVNTSU9OIElORk8gVE8gRE8KCmBgYHtyIHNldHVwfQpsaWJyYXJ5KGRhdGEudGFibGUpCmxpYnJhcnkodmVnYW4pCmxpYnJhcnkoc2YpCmxpYnJhcnkoY29uY2F2ZW1hbikgI3BvbHlnb24gYXJvdW5kIHBvaW50cwpsaWJyYXJ5KGJldGFwYXJ0KSAjYWxsb3dzIHVzIHRvIHBhcnRpdGlvbiBiZXRhIGRpdmVyc2l0eQpsaWJyYXJ5KGdlb3NwaGVyZSkKbGlicmFyeShnZ3B1YnIpICNzdGF0X3JlZ2xpbmVfZXF1YXRpb24KbGlicmFyeShubG1lKQpsaWJyYXJ5KG1nY3YpICN0byBtYWtlIGdhbQpsaWJyYXJ5KGNvd3Bsb3QpCmxpYnJhcnkobG1lNCkKCiNQdWxsIERpc3NpbWlsYXJpdHkgTWVhbnMKZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yIDwtIHJlYWRSRFMoaGVyZTo6aGVyZSgib3V0cHV0IiwiZGlzc2ltaWxhcml0aWVzIiwgImRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuci5yZHMiKSkKCiNtYWtlIHN1cnZleSBhbmQgc3VydmV5IHVuaXQgZmFjdG9ycwpkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbLHN1cnZleTo9ZmFjdG9yKHN1cnZleSldWyxzdXJ2ZXlfdW5pdDo9ZmFjdG9yKHN1cnZleV91bml0KV0KCiNhZGp1c3QgeWVhcnMKZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyx5ZWFyX2FkaiA6PSB5ZWFyLW1pbih5ZWFyKSsxXQoKI2FkZCBuZXcgdmFyaWFibGUgZm9yIHllYXIgaW4gc2VxdWVuY2UgcGVyIHJlZ2lvbgpkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbLGZpcnN0X3llYXIgOj0gbWluKHllYXIpLC4oc3VydmV5X3VuaXQpXQpkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbLGxhc3RfeWVhciA6PSBtYXgoeWVhciksLihzdXJ2ZXlfdW5pdCldCgojZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyx5ZWFyX2luX3NlcSA6PSB5ZWFyLWZpcnN0X3llYXIrMV0KCmRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclsseWVhcnNfc2FtcGxlZCA6PSBsYXN0X3llYXItZmlyc3RfeWVhcisxXQoKCmBgYAoKIyMjUGFsZXR0ZSBmb3IgUGxvdHRpbmcKUGFsZXR0ZSBmb3IgcGxvdHRpbmcgYWxsIDM3IHN1cnZleSB1bml0cwpgYGB7ciBsaW5rIGNvbG9ycyB0byBzdXJ2ZXkgdW5pdHN9CnN1cnZleV91bml0Lmxpc3QgPC0gbGV2ZWxzKGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclssc3VydmV5X3VuaXRdKQoKcGFsZXR0ZV80MiA8LSBjKAogICIjNUE1MTU2IiwgI0FJCiAgIiNERjAwREIiLCAjQklUUy0xCiAgIiNEQjhFREEiLCAjQklUUy00CiAgIiNGNjIyMkUiLCAjQ0hMCiAgIiNGOEExOUYiLCAjREZPLU5GCiAgIiMxNkZGMzIiLCAjREZPLVFDUwogICIjMzI1QTlCIiwgI0VCUwogICIjMzI4M0ZFIiwgI0VWSE9FCiAgIiNGRUFGMTYiLCAjRlItQ0dGUwogICIjZmNjYjZkIiwgI0dNRVgtRmFsbAogICIjMUM4MzU2IiwgI0dNRVgtU3VtbWVyCiAgIiNDNDQ1MUMiLCAjR09BCiAgIiM4NTY2MEQiLCAjR1JMLURFCiAgIiNCMDAwOUYiLCAjR1NMLU4KICAiI0JGNzlCOCIsICNHU0wtUwogICIjMUNCRTRGIiwgI0lDRS1HRlMKICAiIzc4MkFCNiIsICNJRS1JR0ZTCiAgIiM5MEFEMUMiLCAjTUVESVRTCiAgIiM2QjAwM0EiLCAjTkFNCiAgIiNBNzVCMDAiLCAjTkVVUy1GYWxsCiAgIiNFM0IwNzIiLCAjTkVVUy1TcHJpbmcKICAiIzAyRThCNiIsICNOSUdGUy0xCiAgIiM5N0U3RDUiLCAjTklHRlMtNAogICIjQjAwMDY4IiwgI05vci1CVFMtMwogICIjMDBCOUUzIiwgI05TLUlCVFMtMQogICIjOTVFMkY0IiwgI05TLUlCVFMtMwogICIjQjNDRTczIiwgI05aLUNIQVQKICAiIzY4OTUwMCIsICNOWi1FQ1NJCiAgIiMzNjRkMDIiLCNOWi1TVUJBCiAgIiNBQUY0MDAiLCAjTlotV0NTSQogICIjQUEwREZFIiwgI1BULUlCVFMKICAiIzdmOWViOCIsICNST0NLQUxMCiAgIiNGQTAwODciLCAjUy1HRU9SRwogICIjREVBMEZEIiwgI1NDUy1TdW1tZXIKICAiI0ZDRUY4OCIsICNTRVVTLWZhbGwKICAiI0E1OTQwNSIsICNTRVVTLXNwcmluZwogICIjRkNFMTAwIiwgI1NFVVMtc3VtbWVyCiAgIiM1NDQ1NjMiLCAjU1dDLUlCVFMtMQogICIjYTM3ZmM3IiwgI1NXQy1JQlRTLTQKICAiI0MwNzVBNiIsICNXQ0FOTgogICIjQkRDREZGIiwgI1pBRi1BVEwKICAiIzAwM0VGRiIgICNaQUYtSU5ECikKCmNvbG9yX2xpbmsgPC0gZGF0YS50YWJsZShzdXJ2ZXlfdW5pdCA9IHN1cnZleV91bml0Lmxpc3QsaGV4ID0gcGFsZXR0ZV80MikKYGBgCgpBZGQgbmFtZXMgZm9yIHBsb3R0aW5nCmBgYHtyIGFkZCBuYW1lcyBmb3IgcGxvdHRpbmd9CgpuYW1lX2hlbHBlciA8LSBkYXRhLnRhYmxlKFN1cnZleV9OYW1lX1NlYXNvbiA9IGMoIkFsZXV0aWFuIElzbGFuZHMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQmFsdGljIFNlYSBRMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJCYWx0aWMgU2VhIFE0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNoaWxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5ld2ZvdW5kbGFuZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJRdWVlbiBDaGFybG90dGUgU291bmQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRWFzdGVybiBCZXJpbmcgU2VhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkJheSBvZiBCaXNjYXkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRW5nbGlzaCBDaGFubmVsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkd1bGYgb2YgTWV4aWNvIFN1bW1lciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHdWxmIG9mIEFsYXNrYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHcmVlbmxhbmQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTiBHdWxmIG9mIFN0LiBMYXdyZW5jZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTIEd1bGYgb2YgU3QuIExhd3JlbmNlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkljZWxhbmQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSXJpc2ggU2VhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1lZGl0ZXJyYW5lYW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTmFtaWJpYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJORSBVUyBGYWxsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5FIFVTIFNwcmluZyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOIElyZWxhbmQgUTEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTiBJcmVsYW5kIFE0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkJhcmVudHMgU2VhIE5vcndheSBRMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOIFNlYSBRMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOIFNlYSBRMyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDaGF0aGFtIFJpc2UgTloiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRSBDb2FzdCBTIElzbGFuZCBOWiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJXIENvYXN0IFMgSXNsYW5kIE5aIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBvcnR1Z2FsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlMgR2VvcmdpYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU2NvdGlhbiBTaGVsZiBTdW1tZXIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNFIFVTIEZhbGwiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNFIFVTIFNwcmluZyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU0UgVVMgU3VtbWVyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJXIENvYXN0IFVTIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBdGxhbnRpYyBPY2VhbiBaQSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSW5kaWFuIE9jZWFuIFpBIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUm9ja2FsbCBQbGF0ZWF1IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTY290bGFuZCBTaGVsZiBTZWEgUTEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNjb3RsYW5kIFNoZWxmIFNlYSBRNCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRmFsa2xhbmQgSXNsYW5kcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR3VsZiBvZiBNZXhpY28gRmFsbCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQmFyZW50cyBTZWEgTm9yd2F5IFExIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTdWItQXJjdGljIE5aIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTY290aWFuIFNoZWxmIFNwcmluZyIpLAogICAgICAgICAgICAgICAgICAgICAgICAgIHN1cnZleV91bml0ID0gYygKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJBSSIsICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJCSVRTLTEiLCAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJCSVRTLTQiLCAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDSEwiLCAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJERk8tTkYiLCAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJERk8tUUNTIiwgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJFQlMiLCAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJFVkhPRSIsICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJGUi1DR0ZTIiwgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHTUVYLVN1bW1lciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR09BIiwgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR1JMLURFIiwgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR1NMLU4iLCAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR1NMLVMiLCAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSUNFLUdGUyIsICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSUUtSUdGUyIsICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTUVESVRTIiwgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTkFNIiwgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTkVVUy1GYWxsIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTkVVUy1TcHJpbmciLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5JR0ZTLTEiLCAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5JR0ZTLTQiLCAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5vci1CVFMtMyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5TLUlCVFMtMSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5TLUlCVFMtMyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5aLUNIQVQiLCAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5aLUVDU0kiLCAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5aLVdDU0kiLCAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBULUlCVFMiLCAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlMtR0VPUkciLCAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNDUy1TVU1NRVIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNFVVMtZmFsbCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNFVVMtc3ByaW5nIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTRVVTLXN1bW1lciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV0NBTk4iLCAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiWkFGLUFUTCIsICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiWkFGLUlORCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUk9DS0FMTCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU1dDLUlCVFMtMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU1dDLUlCVFMtNCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRkFMSyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR01FWC1GYWxsIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOb3ItQlRTLTEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5aLVNVQkEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNDUy1TUFJJTkciCiAgICAgICAgICAgICAgICAgICAgICAgICAgKSkKCgpjb2xvcl9saW5rIDwtIGNvbG9yX2xpbmtbbmFtZV9oZWxwZXIsIG9uID0gInN1cnZleV91bml0Il0KCmBgYAoKCgojI01ha2UgR0FNcwoKQnJheSBDdXJ0aXMKYGBge3IgYnJheSBjdXJ0aXMgZ2Ftc30KYnJheV9jdXJ0aXNfZ3JhZGllbnRfZ2FtIDwtIGdhbShicmF5X2N1cnRpc19kaXNzaW1pbGFyaXR5X2dyYWRpZW50X21lYW4gfiB5ZWFyICsgcyhzdXJ2ZXlfdW5pdCwgeWVhciwgYnMgPSAiZnMiLCBtID0gMSksI3JhbmRvbSBzbW9vdGgKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnIpCgpgYGAKCgojI01ha2UgTE1FUlMKCkJyYXkKKlRoZXNlIGFsbCBjb252ZXJnZWQqCmBgYHtyIGJyYXl9CiNydW5uaW5nIHdpdGggbG1lIGluc3RlYWQgb2YgbG1lciBnYXZlIHNhbWUgcmVzdWx0cywgYnV0IGFsbG93ZWQgZm9yIGNhbGN1bGF0aW9uIG9mIHAtdmFsdWUKYnJheV9jdXJ0aXNfZ3JhZGllbnRfbG1lIDwtIGxtZShicmF5X2N1cnRpc19kaXNzaW1pbGFyaXR5X2dyYWRpZW50X21lYW4gfiB5ZWFyX2FkaiwgcmFuZG9tID0gKH4xICsgeWVhcl9hZGp8c3VydmV5X3VuaXQpLGRhdGEgPSBkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnIpCgojYnV0IGFsc28gcnVuIHdpdGggbG1lciBmb3IgY29uZmludApicmF5X2N1cnRpc19ncmFkaWVudF9sbWVyIDwtIGxtZXIoYnJheV9jdXJ0aXNfZGlzc2ltaWxhcml0eV9ncmFkaWVudF9tZWFuIH4geWVhcl9hZGogKyAoMSArIHllYXJfYWRqfHN1cnZleV91bml0KSxkYXRhID0gZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yKQoKc3VtbWFyeShicmF5X2N1cnRpc19ncmFkaWVudF9sbWUpCmFub3ZhKGJyYXlfY3VydGlzX2dyYWRpZW50X2xtZSkKCmJyYXlfY3VydGlzX2dyYWRpZW50X2NvZWZzIDwtIGRhdGEudGFibGUoY29lZihicmF5X2N1cnRpc19ncmFkaWVudF9sbWUpKQpicmF5X2N1cnRpc19ncmFkaWVudF9jb2Vmc1ssc3VydmV5X3VuaXQgOj0gcm93bmFtZXMoY29lZihicmF5X2N1cnRpc19ncmFkaWVudF9sbWUpKV1bLFllYXIgOj0gcm91bmQoeWVhcl9hZGosNSldWyxJbnRlcmNlcHQgOj0gcm91bmQoYChJbnRlcmNlcHQpYCwyKV0KVmlldyhicmF5X2N1cnRpc19ncmFkaWVudF9jb2VmcykKCmJyYXlfY3VydGlzX2dyYWRpZW50X2NvZWZzIDwtIGJyYXlfY3VydGlzX2dyYWRpZW50X2NvZWZzW2NvbG9yX2xpbmssIG9uID0gInN1cnZleV91bml0Il0KCmJyYXlfY3VydGlzX2dyYWRpZW50X2NvZWZzLmV4cCA8LSBicmF5X2N1cnRpc19ncmFkaWVudF9jb2Vmc1ssLihTdXJ2ZXlfTmFtZV9TZWFzb24sIEludGVyY2VwdCwgWWVhcildCgojZXhwb3J0IHRoaXMgdGFibGUKZndyaXRlKGJyYXlfY3VydGlzX2dyYWRpZW50X2NvZWZzLmV4cCwgZmlsZSA9IGhlcmU6OmhlcmUoIm91dHB1dCIsImJyYXlfY3VydGlzX2dyYWRpZW50X2NvZWZzLmV4cC5jc3YiKSkKYGBgCgpHZXQgTE1FUiBtb2RlbCBhcyBwcmVkaWN0aW9ucwpgYGB7cn0KCiMgbmVlZCB0byBzb3J0IG91dCB5ZWFyIGluIHNlcSB2ZXJzdXMgb3ZlcmFsbCB5ZWFyIG1vZGVscwojbmV3IGRhdGEgZm9yIGxtZXIKbG1lcl95ZWFyIDwtIHNlcShtaW4oZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyx5ZWFyXSksIG1heChkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbLHllYXJdKSwgYnkgPSAwLjEpCgpsbWVyX3llYXJfYWRqIDwtIHNlcShtaW4oZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyx5ZWFyX2Fkal0pLCBtYXgoZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyx5ZWFyX2Fkal0pLCBieSA9IDAuMSkKCiNwcmVkaWN0IGF2ZXJhZ2UgbG1lcgpsbWVyX2JyYXlfZ3JhZGllbnRfcHJlZGljdGlvbnMgPC0gZGF0YS50YWJsZSh5ZWFyID0gbG1lcl95ZWFyLCB5ZWFyX2FkaiA9IGxtZXJfeWVhcl9hZGopCgojY29uZmlkZW5jZSBpbnRlcnZhbHMKYnJheV9jdXJ0aXNfZ3JhZGllbnRfbG1lcl9jb25maW50IDwtIGNvbmZpbnQoYnJheV9jdXJ0aXNfZ3JhZGllbnRfbG1lcikKCiNwb3B1bGF0ZSBkYXRhIHRhYmxlIG9mIGxtZXIgcHJlZGljdGlvbnMKbG1lcl9icmF5X2dyYWRpZW50X3ByZWRpY3Rpb25zWyxicmF5X2N1cnRpc19sbWVyX3ByZWRzIDo9IGZpeGVmKGJyYXlfY3VydGlzX2dyYWRpZW50X2xtZXIpW1sxXV0gKyBmaXhlZihicmF5X2N1cnRpc19ncmFkaWVudF9sbWVyKVtbMl1dICogeWVhcl9hZGpdWyxicmF5X2N1cnRpc19sbWVyX3ByZWRzX2xvd2VyQ0kgOj0gYnJheV9jdXJ0aXNfZ3JhZGllbnRfbG1lcl9jb25maW50WzVdICsgYnJheV9jdXJ0aXNfZ3JhZGllbnRfbG1lcl9jb25maW50WzZdICogeWVhcl9hZGpdWyxicmF5X2N1cnRpc19sbWVyX3ByZWRzX3VwcGVyQ0kgOj0gYnJheV9jdXJ0aXNfZ3JhZGllbnRfbG1lcl9jb25maW50WzExXSArIGJyYXlfY3VydGlzX2dyYWRpZW50X2xtZXJfY29uZmludFsxMl0gKiB5ZWFyX2Fkal0KYGBgCgoKCiMjI01vdmUgZm9yd2FyZCB3aXRoIEJyYXkgQ3VydGlzIEdyYWRpZW50IChvdGhlcnMgdG8gc3VwcGxlbWVudCkKCgpDb2VmZmljaWVudHMgZm9yIExNRVIgYnkgc3VydmV5X3VuaXQKYGBge3J9CiN1bmlxdWUgc3VydmV5IHVuaXQgeWVhciBjb21ib3MKc3VydmV5X3VuaXRfc2FtcGxpbmdfeWVhcnMgPC0gdW5pcXVlKGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclssLihzdXJ2ZXlfdW5pdCwgeWVhcl9hZGosIHllYXIsIHllYXJzX3NhbXBsZWQpXSkKCiMgc2VlIGdyb3VwIGNvZWZmaWNpZW50cwptb2RlbF9jb2Vmc19yZWR1Y2VkIDwtIGRhdGEudGFibGUodHJhbnNmb3JtKGFzLmRhdGEuZnJhbWUocmFuZWYoYnJheV9jdXJ0aXNfZ3JhZGllbnRfbG1lcikpLCBsd3IgPSBjb25kdmFsIC0gMS45Nipjb25kc2QsIHVwciA9IGNvbmR2YWwgKyAxLjk2KmNvbmRzZCkpCiNodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy82OTgwNTUzMi9leHRyYWN0LXRoZS1jb25maWRlbmNlLWludGVydmFscy1vZi1sbWVyLXJhbmRvbS1lZmZlY3RzLXBsb3R0ZWQtd2l0aC1kb3RwbG90cmEKCgojT05MWSBTTE9QRVMKbW9kZWxfY29lZnNfcmVkdWNlZCA8LSBtb2RlbF9jb2Vmc19yZWR1Y2VkW3Rlcm0gPT0gInllYXJfYWRqIixdCgptb2RlbF9jb2Vmc19yZWR1Y2VkWyxzdXJ2ZXlfdW5pdCA6PSBncnBdWyx5ZWFyX2FkaiA6PSBjb25kdmFsXQoKI21lcmdlIHdpdGggZHVyYXRpb24gb2Ygc3VydmV5Cm1vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoIDwtIG1vZGVsX2NvZWZzX3JlZHVjZWRbc3VydmV5X3VuaXRfc2FtcGxpbmdfeWVhcnMsIG9uID0gInN1cnZleV91bml0Il0KCgptb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aFsseWVhcnNfc2FtcGxlZCA6PSBhcy5udW1lcmljKHllYXJzX3NhbXBsZWQpXVssRGlyZWN0aW9uYWxfQ2hhbmdlIDo9IGlmZWxzZSh5ZWFyX2FkaiA+IDAsICJEaWZmZXJlbnRpYXRpb24iLCJIb21vZ2VuaXphdGlvbiIpXQoKI2RvZXMgaXQgY3Jvc3MgemVybz8KbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGhbLHNpZ25pZmljYW50IDo9IGlmZWxzZShsd3IgPjAgJiB1cHI+MCxULGlmZWxzZShsd3I8MCAmIHVwcjwwLFQsRikpXQoKI3NpZ25pZmljYW50IGRpcmVjdGlvbmFsIGNoYW5nZQptb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aFssRGlyZWN0aW9uYWxfQ2hhbmdlX3NpZyA6PSBpZmVsc2UoeWVhcl9hZGogPiAwICYgc2lnbmlmaWNhbnQgPT0gVCwgIkRpZmZlcmVudGlhdGlvbiIsaWZlbHNlKHllYXJfYWRqIDwgMCAmIHNpZ25pZmljYW50ID09IFQsICJIb21vZ2VuaXphdGlvbiIsICJObyB0cmVuZCBpblxuZGlzc2ltaWxhcml0eSIpKV0KCgojbWluIG1heCBkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzCm1pbl9icmF5X3JlZHVjZWQgPC0gbWluKGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclssYnJheV9jdXJ0aXNfZGlzc2ltaWxhcml0eV9ncmFkaWVudF9tZWFuXSwgbmEucm0gPSBUKQptYXhfYnJheV9yZWR1Y2VkIDwtIG1heChkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbLGJyYXlfY3VydGlzX2Rpc3NpbWlsYXJpdHlfZ3JhZGllbnRfbWVhbl0sIG5hLnJtID0gVCkKCm1vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoIDwtIG1vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoW2NvbG9yX2xpbmssIG9uID0gInN1cnZleV91bml0Il0KCiNkZWxldGUgYW55IE5Bcwptb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aCA8LSBuYS5vbWl0KG1vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoLCBjb2xzID0gInNpZ25pZmljYW50IikKCiNvcmRlciB0YWJsZSBieSBjb2VmZmljaWVudApzZXRvcmRlcihtb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aCwgeWVhcl9hZGopCgpCQ19ncmFkaWVudF9tb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aC51bmlxdWUgPC0gdW5pcXVlKG1vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoWywuKGNvbmR2YWwsY29uZHNkLCBsd3IsIHVwciwgc3VydmV5X3VuaXQsIHllYXJfYWRqLCB5ZWFyc19zYW1wbGVkLCBEaXJlY3Rpb25hbF9DaGFuZ2UsIGhleCwgU3VydmV5X05hbWVfU2Vhc29uLCBzaWduaWZpY2FudCwgRGlyZWN0aW9uYWxfQ2hhbmdlX3NpZyldKSAKCiNleHRyYWN0IGNvbG9yIGhleGVzCiN5ZWFyIGFkaiBjb2VmIG9yZGVyCmNvbG9yX3llYXJfYWRqX29yZGVyIDwtIEJDX2dyYWRpZW50X21vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoLnVuaXF1ZVssaGV4XQoKI2FscGhhYmV0aWNhbCBvcmRlcgpCQ19ncmFkaWVudF9tb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aC51bmlxdWUuYWxwaGEgPC0gc2V0b3JkZXIoQkNfZ3JhZGllbnRfbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGgudW5pcXVlLCBTdXJ2ZXlfTmFtZV9TZWFzb24pCgpCQ19ncmFkaWVudF9tb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aC51bmlxdWUuYWxwaGFbLHRyZW5kX2NvbG9yIDo9IGlmZWxzZShEaXJlY3Rpb25hbF9DaGFuZ2Vfc2lnID09ICJIb21vZ2VuaXphdGlvbiIsICIjZTdhYzViIiwgaWZlbHNlKERpcmVjdGlvbmFsX0NoYW5nZV9zaWcgPT0gIkRpZmZlcmVudGlhdGlvbiIsIiM5MWM4NzQiLCIjY2JiZmRlIikpXQoKY29sb3JfYWxwaGFfb3JkZXIgPC0gQkNfZ3JhZGllbnRfbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGgudW5pcXVlLmFscGhhWyxoZXhdCmNvbG9yX2FscGhhX29yZGVyX2J5dHJlbmQgPC0gQkNfZ3JhZGllbnRfbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGgudW5pcXVlLmFscGhhWywgdHJlbmRfY29sb3JdCgpzYXZlUkRTKEJDX2dyYWRpZW50X21vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoLnVuaXF1ZSwgaGVyZTo6aGVyZSgib3V0cHV0IiwicmVnaW9uX3N0YXRzIiwiQkNfZ3JhZGllbnRfbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGgudW5pcXVlLlJkcyIpKQpgYGAKCkJhciBQbG90IENvZWZmaWNpZW50IExNRVIKYGBge3IgYmFyIHBsb3Qgb2YgY29lZmZpY2llbnRzfQpCQ19HUkFESUVOVF9EaXNzaW1pbGFyaXR5X0NvZWZfZXJyb3JiYXJfcmVkdWNlZCA8LSBnZ3Bsb3QoKSArCiAgICBnZW9tX2Vycm9yYmFyKGRhdGEgPSBtb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aCwgYWVzKHggPSByZW9yZGVyKFN1cnZleV9OYW1lX1NlYXNvbiwgeWVhcl9hZGopICwgeSA9IHllYXJfYWRqLCBsYWJlbCA9IFN1cnZleV9OYW1lX1NlYXNvbiwgeW1pbiA9IGx3ciwgeW1heCA9IHVwciksIGZpbGwgPSAiZ3JleSIsIHdpZHRoID0gMCkgKyAjYWRkIGNvbmZpZGVuY2UgaW50ZXJ2YWxzCiAgZ2VvbV9wb2ludChkYXRhID0gbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGgsIGFlcyh4ID0gcmVvcmRlcihTdXJ2ZXlfTmFtZV9TZWFzb24sIHllYXJfYWRqKSAsIHkgPSB5ZWFyX2FkaiwgbGFiZWwgPSBTdXJ2ZXlfTmFtZV9TZWFzb24sIHNpemUgPSB5ZWFyc19zYW1wbGVkLCBmaWxsID0gRGlyZWN0aW9uYWxfQ2hhbmdlX3NpZywgY29sb3IgPSBEaXJlY3Rpb25hbF9DaGFuZ2Vfc2lnKSwgc3RhdCA9ICdpZGVudGl0eScsIHNoYXBlID0gMjEpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJ3aGl0ZSIsImJsYWNrIiwiZ3JleSIpLCBuYW1lID0gIkRpc3NpbWlsYXJpdHkgdHJlbmQiLCBndWlkZT0ibm9uZSIpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiYmxhY2siLCJibGFjayIsImdyZXkiKSwgbmFtZSA9ICJEaXNzaW1pbGFyaXR5IHRyZW5kIiwgZ3VpZGU9Im5vbmUiKSArCiAgc2NhbGVfc2l6ZV9iaW5uZWQocmFuZ2UgPSBjKDEsOCksIG5hbWUgPSAiU3VydmV5IHBlcmlvZCBsZW5ndGgiKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCkgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoLTAuMDA1LCAwLjAwNzUsIGJ5ID0gMC4wMDI1KSwgbGFiZWxzID0gYygiLTAuMDA1IiwiIiwiMCIsICIiLCAiMC4wMDUiLCAgIiIpKSArCiAgeGxhYigiU3VydmV5IHVuaXQiKSArCiAgeWxhYigizrItZGl2ZXJzaXR5IHRyZW5kIikgKyAjZ3JhZGllbnQgQkMgZGlzc2ltaWxhcml0eSB0cmVuZAogIGNvb3JkX2ZsaXAoKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSBjb2xvcl95ZWFyX2Fkal9vcmRlciwgZmFjZSA9ICJib2xkIiksIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSwgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSksIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC4yLDAuOCksIGxlZ2VuZC5kaXJlY3Rpb24gPSAidmVydGljYWwiLCBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gInRyYW5zcGFyZW50IikpCgojcHVsbCBsZWdlbmQgZm9yIGhvbW9nZW5pemF0aW9uCmRpcmVjdGlvbmFsX2NoYW5nZV9sZWdlbmRfcGxvdCA8LSBCQ19HUkFESUVOVF9EaXNzaW1pbGFyaXR5X0NvZWZfZXJyb3JiYXJfcmVkdWNlZCArIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIndoaXRlIiwiYmxhY2siLCJncmV5IiksIG5hbWUgPSAiRGlzc2ltaWxhcml0eSB0cmVuZCIpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiYmxhY2siLCJibGFjayIsImdyZXkiKSwgbmFtZSA9ICJEaXNzaW1pbGFyaXR5IHRyZW5kIikgKwogIHNjYWxlX3NpemVfYmlubmVkKHJhbmdlID0gYygxLDgpLCBuYW1lID0gIlN1cnZleSBwZXJpb2QgbGVuZ3RoIiwgZ3VpZGUgPSAibm9uZSIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLCBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPSAidHJhbnNwYXJlbnQiKSkgKwogIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChzaXplPTYpKSkKCgpCQ19HUkFESUVOVF9EaXNzaW1pbGFyaXR5X0NvZWZfZXJyb3JiYXJfcmVkdWNlZAoKI0FMVCBncmV5IHNjYWxlCkJDX0dSQURJRU5UX0Rpc3NpbWlsYXJpdHlfQ29lZl9lcnJvcmJhcl9yZWR1Y2VkX2dyZXlzY2FsZSA8LSBnZ3Bsb3QoKSArCiAgICBnZW9tX2Vycm9yYmFyKGRhdGEgPSBtb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aCwgYWVzKHggPSByZW9yZGVyKFN1cnZleV9OYW1lX1NlYXNvbiwgeWVhcl9hZGopICwgeSA9IHllYXJfYWRqLCBsYWJlbCA9IFN1cnZleV9OYW1lX1NlYXNvbiwgeW1pbiA9IGx3ciwgeW1heCA9IHVwciksIGZpbGwgPSAiZ3JleSIsIHdpZHRoID0gMCkgKyAjYWRkIGNvbmZpZGVuY2UgaW50ZXJ2YWxzCiAgZ2VvbV9wb2ludChkYXRhID0gbW9kZWxfY29lZnNfcmVkdWNlZF9sZW5ndGgsIGFlcyh4ID0gcmVvcmRlcihTdXJ2ZXlfTmFtZV9TZWFzb24sIHllYXJfYWRqKSAsIHkgPSB5ZWFyX2FkaiwgbGFiZWwgPSBTdXJ2ZXlfTmFtZV9TZWFzb24sIHNpemUgPSB5ZWFyc19zYW1wbGVkLCBmaWxsID0gRGlyZWN0aW9uYWxfQ2hhbmdlX3NpZywgY29sb3IgPSBEaXJlY3Rpb25hbF9DaGFuZ2Vfc2lnKSwgc3RhdCA9ICdpZGVudGl0eScsIHNoYXBlID0gMjEpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJ3aGl0ZSIsImJsYWNrIiwiZ3JleSIpLCBuYW1lID0gIkRpc3NpbWlsYXJpdHkgdHJlbmQiLCBndWlkZT0ibm9uZSIpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiYmxhY2siLCJibGFjayIsImdyZXkiKSwgbmFtZSA9ICJEaXNzaW1pbGFyaXR5IHRyZW5kIiwgZ3VpZGU9Im5vbmUiKSArCiAgc2NhbGVfc2l6ZV9iaW5uZWQocmFuZ2UgPSBjKDEsOCksIG5hbWUgPSAiU3VydmV5IHBlcmlvZCBsZW5ndGgiKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCkgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoLTAuMDA1LCAwLjAwNzUsIGJ5ID0gMC4wMDI1KSwgbGFiZWxzID0gYygiLTAuMDA1IiwiIiwiMCIsICIiLCAiMC4wMDUiLCAgIiIpKSArCiAgeGxhYigiU3VydmV5IHVuaXQiKSArCiAgeWxhYigizrItZGl2ZXJzaXR5IHRyZW5kIikgKyAjZ3JhZGllbnQgQkMgZGlzc2ltaWxhcml0eSB0cmVuZAogIGNvb3JkX2ZsaXAoKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSwgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLCBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSwgbGVnZW5kLnBvc2l0aW9uID0gYygwLjI1LDAuOCksIGxlZ2VuZC5kaXJlY3Rpb24gPSAidmVydGljYWwiKQpgYGAKQWx0ZXJuYXRpdmVseSwgd2UgY29sb3IgIHRoaXMgcGxvdCBieSB0cmVuZCBleHBlcmllbmNlZAoKYGBge3J9CiMiIzczQkE0RCIsIiNFMDk2MkMiLCIjY2JiZmRlIgoKQkNfZ3JhZGllbnRfRGlzc2ltaWxhcml0eV9Db2VmX2Vycm9yYmFyX3JlZHVjZWRfY29sb3JieXRyZW5kIDwtIGdncGxvdCgpICsKICAgIGdlb21fZXJyb3JiYXIoZGF0YSA9IG1vZGVsX2NvZWZzX3JlZHVjZWRfbGVuZ3RoLCBhZXMoeCA9IHJlb3JkZXIoU3VydmV5X05hbWVfU2Vhc29uLCB5ZWFyX2FkaikgLCB5ID0geWVhcl9hZGosIGxhYmVsID0gU3VydmV5X05hbWVfU2Vhc29uLCB5bWluID0gbHdyLCB5bWF4ID0gdXByKSwgZmlsbCA9ICJncmV5Iiwgd2lkdGggPSAwKSArICNhZGQgY29uZmlkZW5jZSBpbnRlcnZhbHMKICBnZW9tX3BvaW50KGRhdGEgPSBtb2RlbF9jb2Vmc19yZWR1Y2VkX2xlbmd0aCwgYWVzKHggPSByZW9yZGVyKFN1cnZleV9OYW1lX1NlYXNvbiwgeWVhcl9hZGopICwgeSA9IHllYXJfYWRqLCBsYWJlbCA9IFN1cnZleV9OYW1lX1NlYXNvbiwgc2l6ZSA9IHllYXJzX3NhbXBsZWQsIGNvbG9yID0gRGlyZWN0aW9uYWxfQ2hhbmdlX3NpZyksIHN0YXQgPSAnaWRlbnRpdHknKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIiM3M0JBNEQiLCIjRTA5NjJDIiwiI2NiYmZkZSIpLCBuYW1lID0gIkRpc3NpbWlsYXJpdHkgdHJlbmQiLCBndWlkZT0ibm9uZSIpICsKICBzY2FsZV9zaXplX2Jpbm5lZChyYW5nZSA9IGMoMSw4KSwgbmFtZSA9ICJTdXJ2ZXkgcGVyaW9kIGxlbmd0aFxuKHllYXJzKSIpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwKSArCiMgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoLTAuMDA1LCAwLjAwNzUsIGJ5ID0gMC4wMDI1KSwgbGFiZWxzID0gYygiLTAuMDA1IiwiIiwiMCIsICIiLCAiMC4wMDUiLCAgIiIpKSArCiAgeGxhYigiU3VydmV5IHVuaXQiKSArCiAgeWxhYigizrItZGl2ZXJzaXR5IHRyZW5kIikgKyAjZ3JhZGllbnQgQkMgZGlzc2ltaWxhcml0eSB0cmVuZAogIGNvb3JkX2ZsaXAoKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSwgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLCBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSwgbGVnZW5kLnBvc2l0aW9uID0gYygwLjI1LDAuOCksIGxlZ2VuZC5kaXJlY3Rpb24gPSAidmVydGljYWwiLCBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpLCBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSwgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ0cmFuc3BhcmVudCIpKQoKZGlyZWN0aW9uYWxfY2hhbmdlX2xlZ2VuZF9wbG90X2NvbG9yYnl0cmVuZCA8LSBCQ19ncmFkaWVudF9EaXNzaW1pbGFyaXR5X0NvZWZfZXJyb3JiYXJfcmVkdWNlZF9jb2xvcmJ5dHJlbmQgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLCBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPSAidHJhbnNwYXJlbnQiKSwgCiAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCksIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpKSArCiAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNpemU9NikpLCBzaXplID0gIm5vbmUiKQpgYGAKCldhdnkgTGluZSBQbG90IGZvciBHQU1zCgpHZW5lcmF0ZSBwcmVkaWN0ZWQgdmFsdWVzCmBgYHtyIGdlbmVyYXRlIHByZWRpY3RlZCB2YWx1ZXMgR0FNfQoKI2FkZCBjb2xvcnMgYW5kIG5hbWVzIHRvIGZ1bGwgZGlzc2ltaWxhcml0eSBkYXRhIHRhYmxlCmRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuciA8LSBkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbY29sb3JfbGluaywgb24gPSAic3VydmV5X3VuaXQiXQoKI2dlbmVyYXRlIG5ldyBkYXRhIHRvIHNtb290aCBsaW5lcyAobmVlZCB5ZWFyIGFuZCBzZWFzb24gc3VydmV5IGNvbWJpbmF0aW9ucykKeWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHQgPC0gZGF0YS50YWJsZShzdXJ2ZXlfdW5pdCA9IGFzLmNoYXJhY3RlcihOVUxMKSwgeWVhciA9IGFzLm51bWVyaWMoTlVMTCksIHllYXJfYWRqID0gYXMubnVtZXJpYyhOVUxMICkpCgpmb3IgKGkgaW4gMTpsZW5ndGgoc3VydmV5X3VuaXQubGlzdCkpIHsKICAjZ2VuZXJhdGUgeWVhciB2ZWN0b3JzCiAgc3VydmV5X3VuaXRfeWVhcnMgPC0gdW5pcXVlKGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMucltzdXJ2ZXlfdW5pdCA9PSBzdXJ2ZXlfdW5pdC5saXN0W2ldLC4oc3VydmV5X3VuaXQsIHllYXIsIHllYXJfYWRqKV0pCiAgCiAgeWVhcnMgPC0gc2VxKG1pbihzdXJ2ZXlfdW5pdF95ZWFyc1sseWVhcl0pLCBtYXgoc3VydmV5X3VuaXRfeWVhcnNbLHllYXJdKSwgYnkgPSAwLjEpCiAgCiAgeWVhcl9hZGp1c3QgPC0gc2VxKG1pbihzdXJ2ZXlfdW5pdF95ZWFyc1sseWVhcl9hZGpdKSwgbWF4KHN1cnZleV91bml0X3llYXJzWyx5ZWFyX2Fkal0pLCBieSA9IDAuMSkKICAKICB5ZWFyX3N1cnZleV91bml0X2V4cGFuZC5kdF9hZGRpdGlvbiA8LSBkYXRhLnRhYmxlKHN1cnZleV91bml0ID0gc3VydmV5X3VuaXQubGlzdFtpXSwgeWVhciA9IHllYXJzLCB5ZWFyX2FkaiA9IHllYXJfYWRqdXN0KQogIAogIHllYXJfc3VydmV5X3VuaXRfZXhwYW5kLmR0IDwtIHJiaW5kKHllYXJfc3VydmV5X3VuaXRfZXhwYW5kLmR0LCB5ZWFyX3N1cnZleV91bml0X2V4cGFuZC5kdF9hZGRpdGlvbikKfQoKI2FkZCBjb2xvcnMgYW5kIG5hbWVzIHRvIGZ1bGwgeWVhciBhbmQgc3VydmV5IHVuaXQgY29tYmluYXRpb24gdGFibGUKeWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHQgPC0geWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHRbY29sb3JfbGluaywgb24gPSAic3VydmV5X3VuaXQiXQpgYGAKCgoKR2V0IG1vZGVsIGFzIHByZWRpY3Rpb25zCmBgYHtyfQojZm9yIHBsb3R0aW5nLCBnZXQgbW9kZWwgYXMgcHJlZGljdGlvbnMKYnJheV9jdXJ0aXNfZ3JhZGllbnRfZ2FtX3ByZWRpY3Rpb25zIDwtIHByZWRpY3QoYnJheV9jdXJ0aXNfZ3JhZGllbnRfZ2FtLCBzZS5maXQgPSBUUlVFLCBuZXdkYXRhID0geWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHQpCgojbWVyZ2UgaW50byB0YWJsZQp5ZWFyX3N1cnZleV91bml0X2V4cGFuZC5kdFssYnJheV9nbG1fbW9kX2ZpdCA6PSBicmF5X2N1cnRpc19ncmFkaWVudF9nYW1fcHJlZGljdGlvbnMkZml0XVssYnJheV9nbG1fbW9kX2ZpdF9TRSA6PSBicmF5X2N1cnRpc19ncmFkaWVudF9nYW1fcHJlZGljdGlvbnMkc2UuZml0XQoKYGBgCgoKUHJvZHVjZSBQbG90IG9mIEdBTSBhbmQgbWVhbiBMTUVSIGxpbmUKYGBge3IgcGxvdCBHQU0gYW5kIG1lYW4gTE1FUiBsaW5lc30KcG9pbnRzX3dhdnlsaW5lc19icmF5X2dyYWRpZW50X3llYXJfcmVkdWNlZF9nYW1fbm9sbWVyIDwtIGdncGxvdCgpICsKICMgZ2VvbV9yaWJib24oZGF0YSA9IGxtZXJfYnJheV9ncmFkaWVudF9wcmVkaWN0aW9ucywgYWVzKHggPSB5ZWFyLCB5bWluID0gYnJheV9jdXJ0aXNfbG1lcl9wcmVkc19sb3dlckNJLCB5bWF4ID0gYnJheV9jdXJ0aXNfbG1lcl9wcmVkc191cHBlckNJKSwgZmlsbCA9ICJncmV5IiwgYWxwaGEgPSAwLjIpICsKICBnZW9tX3BvaW50KGRhdGEgPSBuYS5vbWl0KGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMucixjb2xzID0gInllYXJfYWRqIiksCiAgICAgICAgICAgICBhZXMoeCA9IHllYXIsCiAgICAgICAgICAgICAgICAgeSA9IGJyYXlfY3VydGlzX2Rpc3NpbWlsYXJpdHlfZ3JhZGllbnRfbWVhbiwKICAgICAgICAgICAgICAgICBjb2xvciA9IFN1cnZleV9OYW1lX1NlYXNvbiksIGFscGhhID0gMC41LCBzaXplID0gMSkgKwogICAgZ2VvbV9saW5lKGRhdGEgPSBuYS5vbWl0KHllYXJfc3VydmV5X3VuaXRfZXhwYW5kLmR0LGNvbHMgPSAieWVhcl9hZGoiKSwKICAgICAgICAgICAgIGFlcyh4ID0geWVhciwKICAgICAgICAgICAgICAgICB5ID0gYnJheV9nbG1fbW9kX2ZpdCwKICAgICAgICAgICAgICAgICBjb2xvciA9IFN1cnZleV9OYW1lX1NlYXNvbikpICsKICBnZW9tX3JpYmJvbihkYXRhID0gbmEub21pdCh5ZWFyX3N1cnZleV91bml0X2V4cGFuZC5kdCxjb2xzID0gInllYXJfYWRqIiksIGFlcyh4ID0geWVhciwgeW1pbj1icmF5X2dsbV9tb2RfZml0LWJyYXlfZ2xtX21vZF9maXRfU0UsIHltYXg9YnJheV9nbG1fbW9kX2ZpdCticmF5X2dsbV9tb2RfZml0X1NFLCBmaWxsID0gIFN1cnZleV9OYW1lX1NlYXNvbiksIGFscGhhPTAuMSkgKyAjYWRkIHN0YW5kYXJkIGVycm9yCiAjIGdlb21fbGluZShkYXRhID0gbG1lcl9icmF5X2dyYWRpZW50X3ByZWRpY3Rpb25zLCBhZXMoeCA9IHllYXIsIHkgPSBicmF5X2N1cnRpc19sbWVyX3ByZWRzKSwgY29sb3IgPSAiYmxhY2siKSArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gIGNvbG9yX2FscGhhX29yZGVyLCBuYW1lID0gIlN1cnZleSBVbml0IikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9ICBjb2xvcl9hbHBoYV9vcmRlciwgZ3VpZGUgPSAibm9uZSIpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIGxpbXMoeCA9IGMobWluKGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclsseWVhcl0pLG1heChkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbLHllYXJdKSksCiAgICAgICB5ID0gYygwLDAuNSkpICsKICB4bGFiKCJZZWFyIikgKwp5bGFiKCJHcmFkaWVudCBCQyBkaXNzaW1pbGFyaXR5IikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJudWxsIikKCnBvaW50c193YXZ5bGluZXNfYnJheV9ncmFkaWVudF95ZWFyX3JlZHVjZWRfZ2FtX25vbG1lcgoKZ2dzYXZlKHBvaW50c193YXZ5bGluZXNfYnJheV9ncmFkaWVudF95ZWFyX3JlZHVjZWRfZ2FtX25vbG1lciwgcGF0aCA9IGhlcmU6OmhlcmUoImZpZ3VyZXMiKSwgZmlsZW5hbWUgPSJwb2ludHNfd2F2eWxpbmVzX2JyYXlfZ3JhZGllbnRfeWVhcl9yZWR1Y2VkX2dhbV9ub2xtZXIuanBnIiwgaGVpZ2h0ID0gNSwgd2lkdGggPSA1LCB1bml0ID0gImluIikKCiN3aXRoIGxtZXIKCnBvaW50c193YXZ5bGluZXNfYnJheV9ncmFkaWVudF95ZWFyX3JlZHVjZWRfZ2FtIDwtIGdncGxvdCgpICsKICBnZW9tX3JpYmJvbihkYXRhID0gbG1lcl9icmF5X2dyYWRpZW50X3ByZWRpY3Rpb25zLCBhZXMoeCA9IHllYXIsIHltaW4gPSBicmF5X2N1cnRpc19sbWVyX3ByZWRzX2xvd2VyQ0ksIHltYXggPSBicmF5X2N1cnRpc19sbWVyX3ByZWRzX3VwcGVyQ0kpLCBmaWxsID0gImdyZXkiLCBhbHBoYSA9IDAuMykgKwogIGdlb21fcG9pbnQoZGF0YSA9IG5hLm9taXQoZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yLCBjb2xzID0gInllYXJfYWRqIiksCiAgICAgICAgICAgICBhZXMoeCA9IHllYXIsCiAgICAgICAgICAgICAgICAgeSA9IGJyYXlfY3VydGlzX2Rpc3NpbWlsYXJpdHlfZ3JhZGllbnRfbWVhbiwKICAgICAgICAgICAgICAgICBmaWxsID0gU3VydmV5X05hbWVfU2Vhc29uKSwgYWxwaGEgPSAwLjQsIHNpemUgPSAxLCBzaGFwZSA9IDIxLCBjb2xvciA9ICJ3aGl0ZSIpICsKICAgIGdlb21fbGluZShkYXRhID0gbmEub21pdCh5ZWFyX3N1cnZleV91bml0X2V4cGFuZC5kdCwgY29scyA9ICJ5ZWFyX2FkaiIpLAogICAgICAgICAgICAgYWVzKHggPSB5ZWFyLAogICAgICAgICAgICAgICAgIHkgPSBicmF5X2dsbV9tb2RfZml0LAogICAgICAgICAgICAgICAgIGNvbG9yID0gU3VydmV5X05hbWVfU2Vhc29uKSwgYWxwaGEgPSAwLjYpICsKICBnZW9tX3JpYmJvbihkYXRhID0gbmEub21pdCh5ZWFyX3N1cnZleV91bml0X2V4cGFuZC5kdCwgY29scyA9ICJ5ZWFyX2FkaiIpLCBhZXMoeCA9IHllYXIsIHltaW49YnJheV9nbG1fbW9kX2ZpdC1icmF5X2dsbV9tb2RfZml0X1NFLCB5bWF4PWJyYXlfZ2xtX21vZF9maXQrYnJheV9nbG1fbW9kX2ZpdF9TRSwgZmlsbCA9ICBTdXJ2ZXlfTmFtZV9TZWFzb24pLCBhbHBoYT0wLjEpICsgI2FkZCBzdGFuZGFyZCBlcnJvcgogIGdlb21fbGluZShkYXRhID0gbG1lcl9icmF5X2dyYWRpZW50X3ByZWRpY3Rpb25zLCBhZXMoeCA9IHllYXIsIHkgPSBicmF5X2N1cnRpc19sbWVyX3ByZWRzKSwgY29sb3IgPSAiYmxhY2siKSArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gIGNvbG9yX2FscGhhX29yZGVyLCBuYW1lID0gIlN1cnZleSBVbml0IikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9ICBjb2xvcl9hbHBoYV9vcmRlciwgZ3VpZGUgPSAibm9uZSIpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIGxpbXMoeCA9IGMobWluKGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclsseWVhcl0pLG1heChkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbLHllYXJdKSksCiAgICAgICB5ID0gYygwLDAuNSkpICsKICB4bGFiKCJZZWFyIikgKwp5bGFiKCLOsi1kaXZlcnNpdHkiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm51bGwiLCBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSwgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpKQoKcG9pbnRzX3dhdnlsaW5lc19icmF5X2dyYWRpZW50X3llYXJfcmVkdWNlZF9nYW0KCmdnc2F2ZShwb2ludHNfd2F2eWxpbmVzX2JyYXlfZ3JhZGllbnRfeWVhcl9yZWR1Y2VkX2dhbSwgcGF0aCA9IGhlcmU6OmhlcmUoImZpZ3VyZXMiKSwgZmlsZW5hbWUgPSJwb2ludHNfd2F2eWxpbmVzX2JyYXlfZ3JhZGllbnRfeWVhcl9yZWR1Y2VkX2dhbS5qcGciLCBoZWlnaHQgPSA2LCB3aWR0aCA9IDYsIHVuaXQgPSAiaW4iKQoKI0FMVAojcGxvdCBhbGwsIGJ1dCBzYW1lIGNvbG9yIHNjaGVtZSAoZ3JleSkKcG9pbnRzX3dhdnlsaW5lc19icmF5X2dyYWRpZW50X3llYXJfcmVkdWNlZF9nYW1fZ3JleXNjYWxlIDwtIGdncGxvdCgpICsKICBnZW9tX3JpYmJvbihkYXRhID0gbG1lcl9icmF5X2dyYWRpZW50X3ByZWRpY3Rpb25zLCBhZXMoeCA9IHllYXIsIHltaW4gPSBicmF5X2N1cnRpc19sbWVyX3ByZWRzX2xvd2VyQ0ksIHltYXggPSBicmF5X2N1cnRpc19sbWVyX3ByZWRzX3VwcGVyQ0kpLCBmaWxsID0gImdyZXkiLCBhbHBoYSA9IDAuMykgKwogIGdlb21fcG9pbnQoZGF0YSA9IGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuciwKICAgICAgICAgICAgIGFlcyh4ID0geWVhciwKICAgICAgICAgICAgICAgICB5ID0gYnJheV9jdXJ0aXNfZGlzc2ltaWxhcml0eV9ncmFkaWVudF9tZWFuLAogICAgICAgICAgICAgICAgIGZpbGwgPSBTdXJ2ZXlfTmFtZV9TZWFzb24pLCBhbHBoYSA9IDAuNCwgc2l6ZSA9IDEsIHNoYXBlID0gMjEsIGNvbG9yID0gIndoaXRlIikgKwogICAgZ2VvbV9saW5lKGRhdGEgPSB5ZWFyX3N1cnZleV91bml0X2V4cGFuZC5kdCwKICAgICAgICAgICAgIGFlcyh4ID0geWVhciwKICAgICAgICAgICAgICAgICB5ID0gYnJheV9nbG1fbW9kX2ZpdCwKICAgICAgICAgICAgICAgICBjb2xvciA9IFN1cnZleV9OYW1lX1NlYXNvbiksIGFscGhhID0gMC42KSArCiAgZ2VvbV9yaWJib24oZGF0YSA9IHllYXJfc3VydmV5X3VuaXRfZXhwYW5kLmR0LCBhZXMoeCA9IHllYXIsIHltaW49YnJheV9nbG1fbW9kX2ZpdC1icmF5X2dsbV9tb2RfZml0X1NFLCB5bWF4PWJyYXlfZ2xtX21vZF9maXQrYnJheV9nbG1fbW9kX2ZpdF9TRSwgZmlsbCA9ICBTdXJ2ZXlfTmFtZV9TZWFzb24pLCBhbHBoYT0wLjEpICsgI2FkZCBzdGFuZGFyZCBlcnJvcgogIGdlb21fbGluZShkYXRhID0gbG1lcl9icmF5X2dyYWRpZW50X3ByZWRpY3Rpb25zLCBhZXMoeCA9IHllYXIsIHkgPSBicmF5X2N1cnRpc19sbWVyX3ByZWRzKSwgY29sb3IgPSAiYmxhY2siKSArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gIHJlcCgiYmxhY2siLCB0aW1lcyA9IGxlbmd0aCh1bmlxdWUoZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yJFN1cnZleV9OYW1lX1NlYXNvbikpKSwgbmFtZSA9ICJTdXJ2ZXkgVW5pdCIpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSAgcmVwKCJibGFjayIsIHRpbWVzID0gbGVuZ3RoKHVuaXF1ZShkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnIkU3VydmV5X05hbWVfU2Vhc29uKSkpLCBndWlkZSA9ICJub25lIikgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgbGltcyh4ID0gYyhtaW4oZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyx5ZWFyXSksbWF4KGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMuclsseWVhcl0pKSwKICAgICAgIHkgPSBjKDAsMC41KSkgKwogIHhsYWIoIlllYXIiKSArCnlsYWIoIs6yLWRpdmVyc2l0eSIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibnVsbCIsIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpLCBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSkpCgpwb2ludHNfd2F2eWxpbmVzX2JyYXlfZ3JhZGllbnRfeWVhcl9yZWR1Y2VkX2dhbV9ncmV5c2NhbGUKCmdnc2F2ZShwb2ludHNfd2F2eWxpbmVzX2JyYXlfZ3JhZGllbnRfeWVhcl9yZWR1Y2VkX2dhbV9ncmV5c2NhbGUsIHBhdGggPSBoZXJlOjpoZXJlKCJmaWd1cmVzIiksIGZpbGVuYW1lID0icG9pbnRzX3dhdnlsaW5lc19icmF5X2dyYWRpZW50X3llYXJfcmVkdWNlZF9nYW1fZ3JleXNjYWxlLmpwZyIsIGhlaWdodCA9IDYsIHdpZHRoID0gNiwgdW5pdCA9ICJpbiIpCgpgYGAKCkFsdGVybmF0aXZlLCBjb2xvciBieSB0cmVuZApgYGB7ciBjb2xvciB3YXZ5IGxpbmVzIGJ5IHRyZW5kfQoKcG9pbnRzX3dhdnlsaW5lc19icmF5X2dyYWRpZW50X3llYXJfcmVkdWNlZF9nYW1fY29sb3JieXRyZW5kIDwtIGdncGxvdCgpICsKICBnZW9tX3JpYmJvbihkYXRhID0gbG1lcl9icmF5X2dyYWRpZW50X3ByZWRpY3Rpb25zLCBhZXMoeCA9IHllYXIsIHltaW4gPSBicmF5X2N1cnRpc19sbWVyX3ByZWRzX2xvd2VyQ0ksIHltYXggPSBicmF5X2N1cnRpc19sbWVyX3ByZWRzX3VwcGVyQ0kpLCBmaWxsID0gImdyZXkiLCBhbHBoYSA9IDAuMykgKwogIGdlb21fcG9pbnQoZGF0YSA9IG5hLm9taXQoZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yLCBjb2xzID0gInllYXJfYWRqIiksCiAgICAgICAgICAgICBhZXMoeCA9IHllYXIsCiAgICAgICAgICAgICAgICAgeSA9IGJyYXlfY3VydGlzX2Rpc3NpbWlsYXJpdHlfZ3JhZGllbnRfbWVhbiwKICAgICAgICAgICAgICAgICBmaWxsID0gU3VydmV5X05hbWVfU2Vhc29uKSwgYWxwaGEgPSAwLjQsIHNpemUgPSAxLCBzaGFwZSA9IDIxLCBjb2xvciA9ICJ3aGl0ZSIpICsKICAgIGdlb21fbGluZShkYXRhID0gbmEub21pdCh5ZWFyX3N1cnZleV91bml0X2V4cGFuZC5kdCwgY29scyA9ICJ5ZWFyX2FkaiIpLAogICAgICAgICAgICAgYWVzKHggPSB5ZWFyLAogICAgICAgICAgICAgICAgIHkgPSBicmF5X2dsbV9tb2RfZml0LAogICAgICAgICAgICAgICAgIGNvbG9yID0gU3VydmV5X05hbWVfU2Vhc29uKSwgYWxwaGEgPSAwLjYpICsKICBnZW9tX3JpYmJvbihkYXRhID0gbmEub21pdCh5ZWFyX3N1cnZleV91bml0X2V4cGFuZC5kdCwgY29scyA9ICJ5ZWFyX2FkaiIpLCBhZXMoeCA9IHllYXIsIHltaW49YnJheV9nbG1fbW9kX2ZpdC1icmF5X2dsbV9tb2RfZml0X1NFLCB5bWF4PWJyYXlfZ2xtX21vZF9maXQrYnJheV9nbG1fbW9kX2ZpdF9TRSwgZmlsbCA9ICBTdXJ2ZXlfTmFtZV9TZWFzb24pLCBhbHBoYT0wLjEpICsgI2FkZCBzdGFuZGFyZCBlcnJvcgogIGdlb21fbGluZShkYXRhID0gbG1lcl9icmF5X2dyYWRpZW50X3ByZWRpY3Rpb25zLCBhZXMoeCA9IHllYXIsIHkgPSBicmF5X2N1cnRpc19sbWVyX3ByZWRzKSwgY29sb3IgPSAiYmxhY2siKSArCiAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gIGNvbG9yX2FscGhhX29yZGVyX2J5dHJlbmQsIG5hbWUgPSAiU3VydmV5IFVuaXQiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gIGNvbG9yX2FscGhhX29yZGVyX2J5dHJlbmQsIGd1aWRlID0gIm5vbmUiKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICBsaW1zKHggPSBjKG1pbihkaXN0YW5jZXNfZGlzc2ltaWxhcml0aWVzX2FsbHllYXJzLnJbLHllYXJdKSxtYXgoZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yWyx5ZWFyXSkpKSArCiAgeGxhYigiWWVhciIpICsKeWxhYigizrItZGl2ZXJzaXR5IikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJudWxsIiwgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSksIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSkKCnBvaW50c193YXZ5bGluZXNfYnJheV9ncmFkaWVudF95ZWFyX3JlZHVjZWRfZ2FtX2NvbG9yYnl0cmVuZAoKZ2dzYXZlKHBvaW50c193YXZ5bGluZXNfYnJheV9ncmFkaWVudF95ZWFyX3JlZHVjZWRfZ2FtX2NvbG9yYnl0cmVuZCwgcGF0aCA9IGhlcmU6OmhlcmUoImZpZ3VyZXMiKSwgZmlsZW5hbWUgPSJwb2ludHNfd2F2eWxpbmVzX2JyYXlfZ3JhZGllbnRfeWVhcl9yZWR1Y2VkX2dhbV9jb2xvcmJ5dHJlbmQuanBnIiwgaGVpZ2h0ID0gNiwgd2lkdGggPSA2LCB1bml0ID0gImluIikKYGBgCgpgYGB7cn0KI3Bsb3QgZWFjaCBpbmRlcGVuZGVudGx5IGZvciBzdXBwbGVtZW50CiNhbGwgc3VydmV5IG5hbWVzID0gCmFsbF9zdXJ2ZXlfbmFtZXMgPC0gc29ydCh1bmlxdWUoZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yJFN1cnZleV9OYW1lX1NlYXNvbikpCiNsaXN0IG9mIHBsb3RzCnBvaW50c193YXZ5bGluZXNfYnJheV9ncmFkaWVudF95ZWFyX3JlZHVjZWRfZ2FtX2luZGl2aWR1YWwgPC0gbGlzdCgpCmZvciAoaSBpbiAxOmxlbmd0aChhbGxfc3VydmV5X25hbWVzKSkgewpwb2ludHNfd2F2eWxpbmVzX2JyYXlfZ3JhZGllbnRfeWVhcl9yZWR1Y2VkX2dhbV9pbmRpdmlkdWFsW1tpXV0gPC0gZ2dwbG90KCkgKwogIGdlb21fcG9pbnQoZGF0YSA9IGRpc3RhbmNlc19kaXNzaW1pbGFyaXRpZXNfYWxseWVhcnMucltTdXJ2ZXlfTmFtZV9TZWFzb24gPT0gYWxsX3N1cnZleV9uYW1lc1tpXV0sCiAgICAgICAgICAgICBhZXMoeCA9IHllYXIsCiAgICAgICAgICAgICAgICAgeSA9IGJyYXlfY3VydGlzX2Rpc3NpbWlsYXJpdHlfZ3JhZGllbnRfbWVhbiksIGFscGhhID0gMC40LCBjb2xvciA9ICJibGFjayIpICsKICAgIGdlb21fbGluZShkYXRhID0geWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHRbU3VydmV5X05hbWVfU2Vhc29uID09IGFsbF9zdXJ2ZXlfbmFtZXNbaV1dLAogICAgICAgICAgICAgYWVzKHggPSB5ZWFyLAogICAgICAgICAgICAgICAgIHkgPSBicmF5X2dsbV9tb2RfZml0KSwgYWxwaGEgPSAwLjYpICsKICBnZW9tX3JpYmJvbihkYXRhID0geWVhcl9zdXJ2ZXlfdW5pdF9leHBhbmQuZHRbU3VydmV5X05hbWVfU2Vhc29uID09IGFsbF9zdXJ2ZXlfbmFtZXNbaV1dLCBhZXMoeCA9IHllYXIsIHltaW49YnJheV9nbG1fbW9kX2ZpdC1icmF5X2dsbV9tb2RfZml0X1NFLCB5bWF4PWJyYXlfZ2xtX21vZF9maXQrYnJheV9nbG1fbW9kX2ZpdF9TRSksIGFscGhhPTAuMSkgKyAjYWRkIHN0YW5kYXJkIGVycm9yCiAgdGhlbWVfY2xhc3NpYygpICsKIyAgbGltcyh4ID0gYyhtaW4oZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yW1N1cnZleV9OYW1lX1NlYXNvbiA9PSBhbGxfc3VydmV5X25hbWVzW2ldLHllYXJdKSxtYXgoZGlzdGFuY2VzX2Rpc3NpbWlsYXJpdGllc19hbGx5ZWFycy5yW1N1cnZleV9OYW1lX1NlYXNvbiA9PSBhbGxfc3VydmV5X25hbWVzW2ldLHllYXJdKSksCiMgICAgICAgeSA9IGMoMCwwLjUpKSArCiAgeGxhYigiWWVhciIpICsKeWxhYigiYmV0YS1kaXZlcnNpdHkiKSArCiAgZmFjZXRfd3JhcCh+U3VydmV5X05hbWVfU2Vhc29uLCBuY29sID0gNSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJudWxsIiwgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSksIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSkKCnByaW50KHBvaW50c193YXZ5bGluZXNfYnJheV9ncmFkaWVudF95ZWFyX3JlZHVjZWRfZ2FtX2luZGl2aWR1YWxbW2ldXSkKCn0Kc2F2ZVJEUyhwb2ludHNfd2F2eWxpbmVzX2JyYXlfZ3JhZGllbnRfeWVhcl9yZWR1Y2VkX2dhbV9pbmRpdmlkdWFsLCBoZXJlOjpoZXJlKCJmaWd1cmVzIiwicG9pbnRzX3dhdnlsaW5lc19icmF5X2dyYWRpZW50X3llYXJfcmVkdWNlZF9nYW1faW5kaXZpZHVhbC5SZHMiKSkKCiNwcmludCB0byBwZGYKbGlicmFyeShncmlkRXh0cmEpCgpnZ3NhdmUoCiAgIGZpbGVuYW1lID0gaGVyZTo6aGVyZSgiZmlndXJlcyIsInBvaW50c193YXZ5bGluZXNfYnJheV9ncmFkaWVudF95ZWFyX3JlZHVjZWRfZ2FtX2luZGl2aWR1YWwucGRmIiksIAogICBwbG90ID0gbWFycmFuZ2VHcm9iKHBvaW50c193YXZ5bGluZXNfYnJheV9ncmFkaWVudF95ZWFyX3JlZHVjZWRfZ2FtX2luZGl2aWR1YWwsIG5yb3c9MSwgbmNvbD0xKSwgCiAgIHdpZHRoID0gOC41LCBoZWlnaHQgPSAxMQopCgoKYGBgCgpNZXJnZSBCQyB2ZXJzdXMgWWVhciBwbG90IHdpdGggR0FNUyBhbmQgUmVnaW9uIHZzLiBjb2VmZmljaWVudCBwbG90IGZvciBMTUVScwoKYGBge3J9CgpCQ19HUkFESUVOVF9HQU1fTE1FUl9tZXJnZV9sZWdlbmQgPC0gZ2dkcmF3KHhsaW0gPSBjKDAsIDQwLjUpLCB5bGltID0gYygwLCAyMSkpICsKICAgIGRyYXdfcGxvdChwb2ludHNfd2F2eWxpbmVzX2JyYXlfZ3JhZGllbnRfeWVhcl9yZWR1Y2VkX2dhbSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4ID0gMSwgeSA9IDEsIHdpZHRoID0gMjAsIGhlaWdodCA9IDIwKSArCiAgICBkcmF3X3Bsb3QoQkNfR1JBRElFTlRfRGlzc2ltaWxhcml0eV9Db2VmX2Vycm9yYmFyX3JlZHVjZWQgKwogICAgICAgIHRoZW1lKGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMC41LCAnY20nKSwgI2NoYW5nZSBsZWdlbmQga2V5IHNpemUKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiksICNjaGFuZ2UgbGVnZW5kIHRpdGxlIGZvbnQgc2l6ZQogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTQpKSwgI2NoYW5nZSBsZWdlbmQgdGV4dCBmb250IHNpemUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSAyMCwgeSA9IDEsIHdpZHRoID0xOSwgaGVpZ2h0ID0gMjApICsKICAgIGRyYXdfcGxvdChnZXRfbGVnZW5kKGRpcmVjdGlvbmFsX2NoYW5nZV9sZWdlbmRfcGxvdCArIAogICAgICB0aGVtZShsZWdlbmQua2V5LnNpemUgPSB1bml0KDAuNSwgJ2NtJyksICNjaGFuZ2UgbGVnZW5kIGtleSBzaXplCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTUpLCAjY2hhbmdlIGxlZ2VuZCB0aXRsZSBmb250IHNpemUKICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTEzKSkpLCAjY2hhbmdlIGxlZ2VuZCB0ZXh0IGZvbnQgc2l6ZSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IDI3LCB5ID0gMTIsIHdpZHRoID0gMywgaGVpZ2h0ID0gMikgKwogIGdlb21fdGV4dChhZXMoeCA9IDIsIHkgPSAyMC43KSwgbGFiZWwgPSAoImEuIiksIHNpemUgPTgsIGZvbnRmYWNlID0gImJvbGQiKSArCiAgZ2VvbV90ZXh0KGFlcyh4ID0yMCwgeSA9IDIwLjcpLCBsYWJlbCA9ICgiYi4iKSwgc2l6ZSA9OCwgZm9udGZhY2UgPSAiYm9sZCIpCgoKZ2dzYXZlKEJDX0dSQURJRU5UX0dBTV9MTUVSX21lcmdlX2xlZ2VuZCwgcGF0aCA9IGhlcmU6OmhlcmUoImZpZ3VyZXMiKSwgZmlsZW5hbWUgPSAiQkNfR1JBRElFTlRfR0FNX0xNRVJfbWVyZ2VfbGVnZW5kLnBuZyIsIGhlaWdodCA9IDgsIHdpZHRoID0gMTQsIHVuaXRzID0gImluIikKCiNBTFQgR1JFWSBTQ0FMRQpCQ19HUkFESUVOVF9HQU1fTE1FUl9tZXJnZV9sZWdlbmRfZ3JleXNjYWxlIDwtIGdnZHJhdyh4bGltID0gYygwLCA0MC41KSwgeWxpbSA9IGMoMCwgMjEpKSArCiAgICBkcmF3X3Bsb3QocG9pbnRzX3dhdnlsaW5lc19icmF5X2dyYWRpZW50X3llYXJfcmVkdWNlZF9nYW1fZ3JleXNjYWxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSAxLCB5ID0gMSwgd2lkdGggPSAyMCwgaGVpZ2h0ID0gMjApICsKICAgIGRyYXdfcGxvdChCQ19HUkFESUVOVF9EaXNzaW1pbGFyaXR5X0NvZWZfZXJyb3JiYXJfcmVkdWNlZF9ncmV5c2NhbGUgKwogICAgICAgIHRoZW1lKGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMC41LCAnY20nKSwgI2NoYW5nZSBsZWdlbmQga2V5IHNpemUKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiksICNjaGFuZ2UgbGVnZW5kIHRpdGxlIGZvbnQgc2l6ZQogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTQpKSwgI2NoYW5nZSBsZWdlbmQgdGV4dCBmb250IHNpemUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSAyMCwgeSA9IDEsIHdpZHRoID0gMTksIGhlaWdodCA9IDIwKSArCiAgICBkcmF3X3Bsb3QoZ2V0X2xlZ2VuZChkaXJlY3Rpb25hbF9jaGFuZ2VfbGVnZW5kX3Bsb3QgKyAKICAgICAgdGhlbWUobGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjUsICdjbScpLCAjY2hhbmdlIGxlZ2VuZCBrZXkgc2l6ZQogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE1KSwgI2NoYW5nZSBsZWdlbmQgdGl0bGUgZm9udCBzaXplCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xMykpKSwgI2NoYW5nZSBsZWdlbmQgdGV4dCBmb250IHNpemUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IDI3LCB5ID0gMTIsIHdpZHRoID0gMywgaGVpZ2h0ID0gMikgKwogIGdlb21fdGV4dChhZXMoeCA9IDIsIHkgPSAyMC43KSwgbGFiZWwgPSAoImEuIiksIHNpemUgPTgsIGZvbnRmYWNlID0gImJvbGQiKSArCiAgZ2VvbV90ZXh0KGFlcyh4ID0yMCwgeSA9IDIwLjcpLCBsYWJlbCA9ICgiYi4iKSwgc2l6ZSA9OCwgZm9udGZhY2UgPSAiYm9sZCIpCgpnZ3NhdmUoQkNfR1JBRElFTlRfR0FNX0xNRVJfbWVyZ2VfbGVnZW5kX2dyZXlzY2FsZSwgcGF0aCA9IGhlcmU6OmhlcmUoImZpZ3VyZXMiKSwgZmlsZW5hbWUgPSAiQkNfR1JBRElFTlRfR0FNX0xNRVJfbWVyZ2VfbGVnZW5kX2dyZXlzY2FsZS5wbmciLCBoZWlnaHQgPSA4LCB3aWR0aCA9IDE0LCB1bml0cyA9ICJpbiIpCgojQUxUIENPTE9SIEJZIFRSRU5ECkJDX2dyYWRpZW50X0dBTV9MTUVSX21lcmdlX2xlZ2VuZF9jb2xvcmJ5dHJlbmQgPC0gZ2dkcmF3KHhsaW0gPSBjKDAsIDQwLjUpLCB5bGltID0gYygwLCAyMSkpICsKICAgIGRyYXdfcGxvdChwb2ludHNfd2F2eWxpbmVzX2JyYXlfZ3JhZGllbnRfeWVhcl9yZWR1Y2VkX2dhbV9jb2xvcmJ5dHJlbmQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IDEsIHkgPSAxLCB3aWR0aCA9IDIwLCBoZWlnaHQgPSAyMCkgKwogICAgZHJhd19wbG90KEJDX2dyYWRpZW50X0Rpc3NpbWlsYXJpdHlfQ29lZl9lcnJvcmJhcl9yZWR1Y2VkX2NvbG9yYnl0cmVuZCArCiAgICAgICAgdGhlbWUobGVnZW5kLmtleS5zaXplID0gdW5pdCgwLjUsICdjbScpLCAjY2hhbmdlIGxlZ2VuZCBrZXkgc2l6ZQogICAgICAgIyBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiksICNjaGFuZ2UgbGVnZW5kIHRpdGxlIGZvbnQgc2l6ZQogICAgICAgIyBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE0KQogICAgICAgKSwgI2NoYW5nZSBsZWdlbmQgdGV4dCBmb250IHNpemUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSAyMCwgeSA9IDEsIHdpZHRoID0gMTksIGhlaWdodCA9IDIwKSArCiAgICBkcmF3X3Bsb3QoZ2V0X2xlZ2VuZChkaXJlY3Rpb25hbF9jaGFuZ2VfbGVnZW5kX3Bsb3RfY29sb3JieXRyZW5kICsgCiAgICAgIHRoZW1lKGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMC41LCAnY20nKSwgI2NoYW5nZSBsZWdlbmQga2V5IHNpemUKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xNiksICNjaGFuZ2UgbGVnZW5kIHRpdGxlIGZvbnQgc2l6ZQogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTUpKSksICNjaGFuZ2UgbGVnZW5kIHRleHQgZm9udCBzaXplKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSAzNC41LCB5ID0gMy41LCB3aWR0aCA9IDMsIGhlaWdodCA9IDIpICsKICBnZW9tX3RleHQoYWVzKHggPSAyLCB5ID0gMjAuNyksIGxhYmVsID0gKCJhLiIpLCBzaXplID04LCBmb250ZmFjZSA9ICJib2xkIikgKwogIGdlb21fdGV4dChhZXMoeCA9MjAsIHkgPSAyMC43KSwgbGFiZWwgPSAoImIuIiksIHNpemUgPTgsIGZvbnRmYWNlID0gImJvbGQiKQoKZ2dzYXZlKEJDX2dyYWRpZW50X0dBTV9MTUVSX21lcmdlX2xlZ2VuZF9jb2xvcmJ5dHJlbmQsIHBhdGggPSBoZXJlOjpoZXJlKCJmaWd1cmVzIiksIGZpbGVuYW1lID0gIkJDX2dyYWRpZW50X0dBTV9MTUVSX21lcmdlX2xlZ2VuZF9jb2xvcmJ5dHJlbmQucG5nIiwgaGVpZ2h0ID0gOCwgd2lkdGggPSAxNCwgdW5pdHMgPSAiaW4iKQoKYGBgCgo=